Merge branch 'devel-for-2.6.31' into for-2.6.31
Conflicts: fs/nfs/client.c fs/nfs/super.c
This commit is contained in:
commit
1f84603c09
18 changed files with 633 additions and 234 deletions
|
@ -126,7 +126,6 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
|
|||
struct nlm_lock *lock = &argp->lock;
|
||||
|
||||
nlmclnt_next_cookie(&argp->cookie);
|
||||
argp->state = nsm_local_state;
|
||||
memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh));
|
||||
lock->caller = utsname()->nodename;
|
||||
lock->oh.data = req->a_owner;
|
||||
|
@ -165,6 +164,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
|
|||
/* Set up the argument struct */
|
||||
nlmclnt_setlockargs(call, fl);
|
||||
|
||||
lock_kernel();
|
||||
if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
|
||||
if (fl->fl_type != F_UNLCK) {
|
||||
call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
|
||||
|
@ -178,6 +178,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
|
|||
|
||||
fl->fl_ops->fl_release_private(fl);
|
||||
fl->fl_ops = NULL;
|
||||
unlock_kernel();
|
||||
|
||||
dprintk("lockd: clnt proc returns %d\n", status);
|
||||
return status;
|
||||
|
@ -519,6 +520,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
|
|||
|
||||
if (nsm_monitor(host) < 0)
|
||||
goto out;
|
||||
req->a_args.state = nsm_local_state;
|
||||
|
||||
fl->fl_flags |= FL_ACCESS;
|
||||
status = do_vfs_lock(fl);
|
||||
|
|
|
@ -53,7 +53,7 @@ static DEFINE_SPINLOCK(nsm_lock);
|
|||
/*
|
||||
* Local NSM state
|
||||
*/
|
||||
int __read_mostly nsm_local_state;
|
||||
u32 __read_mostly nsm_local_state;
|
||||
int __read_mostly nsm_use_hostnames;
|
||||
|
||||
static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
|
||||
|
@ -112,6 +112,7 @@ static struct rpc_clnt *nsm_create(void)
|
|||
.program = &nsm_program,
|
||||
.version = NSM_VERSION,
|
||||
.authflavor = RPC_AUTH_NULL,
|
||||
.flags = RPC_CLNT_CREATE_NOPING,
|
||||
};
|
||||
|
||||
return rpc_create(&args);
|
||||
|
@ -184,13 +185,19 @@ int nsm_monitor(const struct nlm_host *host)
|
|||
nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
|
||||
|
||||
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
|
||||
if (res.status != 0)
|
||||
if (unlikely(res.status != 0))
|
||||
status = -EIO;
|
||||
if (status < 0)
|
||||
if (unlikely(status < 0)) {
|
||||
printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
|
||||
else
|
||||
nsm->sm_monitored = 1;
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
nsm->sm_monitored = 1;
|
||||
if (unlikely(nsm_local_state != res.state)) {
|
||||
nsm_local_state = res.state;
|
||||
dprintk("lockd: NSM state changed to %d\n", nsm_local_state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -123,7 +123,9 @@ nfs4_callback_up(struct svc_serv *serv)
|
|||
nfs_callback_tcpport6 = ret;
|
||||
dprintk("NFS: Callback listener port = %u (af %u)\n",
|
||||
nfs_callback_tcpport6, PF_INET6);
|
||||
} else if (ret != -EAFNOSUPPORT)
|
||||
} else if (ret == -EAFNOSUPPORT)
|
||||
ret = 0;
|
||||
else
|
||||
goto out_err;
|
||||
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
|
|||
{
|
||||
struct nfs_client *clp;
|
||||
struct rpc_cred *cred;
|
||||
int err = -ENOMEM;
|
||||
|
||||
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
|
||||
goto error_0;
|
||||
|
@ -129,6 +130,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
|
|||
clp->cl_addrlen = cl_init->addrlen;
|
||||
|
||||
if (cl_init->hostname) {
|
||||
err = -ENOMEM;
|
||||
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
|
||||
if (!clp->cl_hostname)
|
||||
goto error_cleanup;
|
||||
|
@ -159,7 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
|
|||
error_cleanup:
|
||||
kfree(clp);
|
||||
error_0:
|
||||
return NULL;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static void nfs4_shutdown_client(struct nfs_client *clp)
|
||||
|
@ -480,9 +482,10 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in
|
|||
spin_unlock(&nfs_client_lock);
|
||||
|
||||
new = nfs_alloc_client(cl_init);
|
||||
} while (new);
|
||||
} while (!IS_ERR(new));
|
||||
|
||||
return ERR_PTR(-ENOMEM);
|
||||
dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new));
|
||||
return new;
|
||||
|
||||
/* install a new client and return with it unready */
|
||||
install_client:
|
||||
|
|
|
@ -68,29 +68,26 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
|
|||
{
|
||||
struct inode *inode = state->inode;
|
||||
struct file_lock *fl;
|
||||
int status;
|
||||
int status = 0;
|
||||
|
||||
if (inode->i_flock == NULL)
|
||||
goto out;
|
||||
|
||||
/* Protect inode->i_flock using the BKL */
|
||||
lock_kernel();
|
||||
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||
continue;
|
||||
if (nfs_file_open_context(fl->fl_file) != ctx)
|
||||
continue;
|
||||
unlock_kernel();
|
||||
status = nfs4_lock_delegation_recall(state, fl);
|
||||
if (status >= 0)
|
||||
continue;
|
||||
switch (status) {
|
||||
default:
|
||||
printk(KERN_ERR "%s: unhandled error %d.\n",
|
||||
__func__, status);
|
||||
case -NFS4ERR_EXPIRED:
|
||||
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client);
|
||||
goto out_err;
|
||||
}
|
||||
if (status < 0)
|
||||
goto out;
|
||||
lock_kernel();
|
||||
}
|
||||
return 0;
|
||||
out_err:
|
||||
unlock_kernel();
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -268,7 +265,10 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
|
|||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
nfs_msync_inode(inode);
|
||||
/* Guard against new delegated open calls */
|
||||
/*
|
||||
* Guard against new delegated open/lock/unlock calls and against
|
||||
* state recovery
|
||||
*/
|
||||
down_write(&nfsi->rwsem);
|
||||
nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||
up_write(&nfsi->rwsem);
|
||||
|
|
|
@ -48,6 +48,9 @@ static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
|
|||
size_t count, unsigned int flags);
|
||||
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos);
|
||||
static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
|
||||
struct file *filp, loff_t *ppos,
|
||||
size_t count, unsigned int flags);
|
||||
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos);
|
||||
static int nfs_file_flush(struct file *, fl_owner_t id);
|
||||
|
@ -73,6 +76,7 @@ const struct file_operations nfs_file_operations = {
|
|||
.lock = nfs_lock,
|
||||
.flock = nfs_flock,
|
||||
.splice_read = nfs_file_splice_read,
|
||||
.splice_write = nfs_file_splice_write,
|
||||
.check_flags = nfs_check_flags,
|
||||
.setlease = nfs_setlease,
|
||||
};
|
||||
|
@ -587,12 +591,38 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
goto out;
|
||||
}
|
||||
|
||||
static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
|
||||
struct file *filp, loff_t *ppos,
|
||||
size_t count, unsigned int flags)
|
||||
{
|
||||
struct dentry *dentry = filp->f_path.dentry;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
ssize_t ret;
|
||||
|
||||
dprintk("NFS splice_write(%s/%s, %lu@%llu)\n",
|
||||
dentry->d_parent->d_name.name, dentry->d_name.name,
|
||||
(unsigned long) count, (unsigned long long) *ppos);
|
||||
|
||||
/*
|
||||
* The combination of splice and an O_APPEND destination is disallowed.
|
||||
*/
|
||||
|
||||
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
|
||||
|
||||
ret = generic_file_splice_write(pipe, filp, ppos, count, flags);
|
||||
if (ret >= 0 && nfs_need_sync_write(filp, inode)) {
|
||||
int err = nfs_do_fsync(nfs_file_open_context(filp), inode);
|
||||
if (err < 0)
|
||||
ret = err;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
|
||||
{
|
||||
struct inode *inode = filp->f_mapping->host;
|
||||
int status = 0;
|
||||
|
||||
lock_kernel();
|
||||
/* Try local locking first */
|
||||
posix_test_lock(filp, fl);
|
||||
if (fl->fl_type != F_UNLCK) {
|
||||
|
@ -608,7 +638,6 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
|
|||
|
||||
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||
out:
|
||||
unlock_kernel();
|
||||
return status;
|
||||
out_noconflict:
|
||||
fl->fl_type = F_UNLCK;
|
||||
|
@ -650,13 +679,11 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
|
|||
* If we're signalled while cleaning up locks on process exit, we
|
||||
* still need to complete the unlock.
|
||||
*/
|
||||
lock_kernel();
|
||||
/* Use local locking if mounted with "-onolock" */
|
||||
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
||||
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||
else
|
||||
status = do_vfs_lock(filp, fl);
|
||||
unlock_kernel();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -673,13 +700,11 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
|
|||
if (status != 0)
|
||||
goto out;
|
||||
|
||||
lock_kernel();
|
||||
/* Use local locking if mounted with "-onolock" */
|
||||
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
||||
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||
else
|
||||
status = do_vfs_lock(filp, fl);
|
||||
unlock_kernel();
|
||||
if (status < 0)
|
||||
goto out;
|
||||
/*
|
||||
|
|
|
@ -42,6 +42,12 @@ struct nfs_clone_mount {
|
|||
rpc_authflavor_t authflavor;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: RFC 1813 doesn't limit the number of auth flavors that
|
||||
* a server can return, so make something up.
|
||||
*/
|
||||
#define NFS_MAX_SECFLAVORS (12)
|
||||
|
||||
/*
|
||||
* In-kernel mount arguments
|
||||
*/
|
||||
|
@ -91,6 +97,8 @@ struct nfs_mount_request {
|
|||
unsigned short protocol;
|
||||
struct nfs_fh *fh;
|
||||
int noresvport;
|
||||
unsigned int *auth_flav_len;
|
||||
rpc_authflavor_t *auth_flavs;
|
||||
};
|
||||
|
||||
extern int nfs_mount(struct nfs_mount_request *info);
|
||||
|
|
|
@ -20,8 +20,116 @@
|
|||
# define NFSDBG_FACILITY NFSDBG_MOUNT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4
|
||||
*/
|
||||
#define MNTPATHLEN (1024)
|
||||
|
||||
/*
|
||||
* XDR data type sizes
|
||||
*/
|
||||
#define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN))
|
||||
#define MNT_status_sz (1)
|
||||
#define MNT_fhs_status_sz (1)
|
||||
#define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE)
|
||||
#define MNT_fhandle3_sz (1 + XDR_QUADLEN(NFS3_FHSIZE))
|
||||
#define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS)
|
||||
|
||||
/*
|
||||
* XDR argument and result sizes
|
||||
*/
|
||||
#define MNT_enc_dirpath_sz encode_dirpath_sz
|
||||
#define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz)
|
||||
#define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \
|
||||
MNT_authflav3_sz)
|
||||
|
||||
/*
|
||||
* Defined by RFC 1094, section A.5
|
||||
*/
|
||||
enum {
|
||||
MOUNTPROC_NULL = 0,
|
||||
MOUNTPROC_MNT = 1,
|
||||
MOUNTPROC_DUMP = 2,
|
||||
MOUNTPROC_UMNT = 3,
|
||||
MOUNTPROC_UMNTALL = 4,
|
||||
MOUNTPROC_EXPORT = 5,
|
||||
};
|
||||
|
||||
/*
|
||||
* Defined by RFC 1813, section 5.2
|
||||
*/
|
||||
enum {
|
||||
MOUNTPROC3_NULL = 0,
|
||||
MOUNTPROC3_MNT = 1,
|
||||
MOUNTPROC3_DUMP = 2,
|
||||
MOUNTPROC3_UMNT = 3,
|
||||
MOUNTPROC3_UMNTALL = 4,
|
||||
MOUNTPROC3_EXPORT = 5,
|
||||
};
|
||||
|
||||
static struct rpc_program mnt_program;
|
||||
|
||||
/*
|
||||
* Defined by OpenGroup XNFS Version 3W, chapter 8
|
||||
*/
|
||||
enum mountstat {
|
||||
MNT_OK = 0,
|
||||
MNT_EPERM = 1,
|
||||
MNT_ENOENT = 2,
|
||||
MNT_EACCES = 13,
|
||||
MNT_EINVAL = 22,
|
||||
};
|
||||
|
||||
static struct {
|
||||
u32 status;
|
||||
int errno;
|
||||
} mnt_errtbl[] = {
|
||||
{ .status = MNT_OK, .errno = 0, },
|
||||
{ .status = MNT_EPERM, .errno = -EPERM, },
|
||||
{ .status = MNT_ENOENT, .errno = -ENOENT, },
|
||||
{ .status = MNT_EACCES, .errno = -EACCES, },
|
||||
{ .status = MNT_EINVAL, .errno = -EINVAL, },
|
||||
};
|
||||
|
||||
/*
|
||||
* Defined by RFC 1813, section 5.1.5
|
||||
*/
|
||||
enum mountstat3 {
|
||||
MNT3_OK = 0, /* no error */
|
||||
MNT3ERR_PERM = 1, /* Not owner */
|
||||
MNT3ERR_NOENT = 2, /* No such file or directory */
|
||||
MNT3ERR_IO = 5, /* I/O error */
|
||||
MNT3ERR_ACCES = 13, /* Permission denied */
|
||||
MNT3ERR_NOTDIR = 20, /* Not a directory */
|
||||
MNT3ERR_INVAL = 22, /* Invalid argument */
|
||||
MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
|
||||
MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
|
||||
MNT3ERR_SERVERFAULT = 10006, /* A failure on the server */
|
||||
};
|
||||
|
||||
static struct {
|
||||
u32 status;
|
||||
int errno;
|
||||
} mnt3_errtbl[] = {
|
||||
{ .status = MNT3_OK, .errno = 0, },
|
||||
{ .status = MNT3ERR_PERM, .errno = -EPERM, },
|
||||
{ .status = MNT3ERR_NOENT, .errno = -ENOENT, },
|
||||
{ .status = MNT3ERR_IO, .errno = -EIO, },
|
||||
{ .status = MNT3ERR_ACCES, .errno = -EACCES, },
|
||||
{ .status = MNT3ERR_NOTDIR, .errno = -ENOTDIR, },
|
||||
{ .status = MNT3ERR_INVAL, .errno = -EINVAL, },
|
||||
{ .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, },
|
||||
{ .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, },
|
||||
{ .status = MNT3ERR_SERVERFAULT, .errno = -ESERVERFAULT, },
|
||||
};
|
||||
|
||||
struct mountres {
|
||||
int errno;
|
||||
struct nfs_fh *fh;
|
||||
unsigned int *auth_count;
|
||||
rpc_authflavor_t *auth_flavors;
|
||||
};
|
||||
|
||||
struct mnt_fhstatus {
|
||||
u32 status;
|
||||
struct nfs_fh *fh;
|
||||
|
@ -35,8 +143,10 @@ struct mnt_fhstatus {
|
|||
*/
|
||||
int nfs_mount(struct nfs_mount_request *info)
|
||||
{
|
||||
struct mnt_fhstatus result = {
|
||||
.fh = info->fh
|
||||
struct mountres result = {
|
||||
.fh = info->fh,
|
||||
.auth_count = info->auth_flav_len,
|
||||
.auth_flavors = info->auth_flavs,
|
||||
};
|
||||
struct rpc_message msg = {
|
||||
.rpc_argp = info->dirpath,
|
||||
|
@ -68,14 +178,14 @@ int nfs_mount(struct nfs_mount_request *info)
|
|||
if (info->version == NFS_MNT3_VERSION)
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
|
||||
else
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
|
||||
|
||||
status = rpc_call_sync(mnt_clnt, &msg, 0);
|
||||
rpc_shutdown_client(mnt_clnt);
|
||||
|
||||
if (status < 0)
|
||||
goto out_call_err;
|
||||
if (result.status != 0)
|
||||
if (result.errno != 0)
|
||||
goto out_mnt_err;
|
||||
|
||||
dprintk("NFS: MNT request succeeded\n");
|
||||
|
@ -86,72 +196,215 @@ int nfs_mount(struct nfs_mount_request *info)
|
|||
|
||||
out_clnt_err:
|
||||
status = PTR_ERR(mnt_clnt);
|
||||
dprintk("NFS: failed to create RPC client, status=%d\n", status);
|
||||
dprintk("NFS: failed to create MNT RPC client, status=%d\n", status);
|
||||
goto out;
|
||||
|
||||
out_call_err:
|
||||
dprintk("NFS: failed to start MNT request, status=%d\n", status);
|
||||
dprintk("NFS: MNT request failed, status=%d\n", status);
|
||||
goto out;
|
||||
|
||||
out_mnt_err:
|
||||
dprintk("NFS: MNT server returned result %d\n", result.status);
|
||||
status = nfs_stat_to_errno(result.status);
|
||||
dprintk("NFS: MNT server returned result %d\n", result.errno);
|
||||
status = result.errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR encode/decode functions for MOUNT
|
||||
*/
|
||||
static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
|
||||
const char *path)
|
||||
{
|
||||
p = xdr_encode_string(p, path);
|
||||
|
||||
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
|
||||
static int encode_mntdirpath(struct xdr_stream *xdr, const char *pathname)
|
||||
{
|
||||
const u32 pathname_len = strlen(pathname);
|
||||
__be32 *p;
|
||||
|
||||
if (unlikely(pathname_len > MNTPATHLEN))
|
||||
return -EIO;
|
||||
|
||||
p = xdr_reserve_space(xdr, sizeof(u32) + pathname_len);
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
xdr_encode_opaque(p, pathname, pathname_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
|
||||
struct mnt_fhstatus *res)
|
||||
static int mnt_enc_dirpath(struct rpc_rqst *req, __be32 *p,
|
||||
const char *dirpath)
|
||||
{
|
||||
struct xdr_stream xdr;
|
||||
|
||||
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
|
||||
return encode_mntdirpath(&xdr, dirpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 1094: "A non-zero status indicates some sort of error. In this
|
||||
* case, the status is a UNIX error number." This can be problematic
|
||||
* if the server and client use different errno values for the same
|
||||
* error.
|
||||
*
|
||||
* However, the OpenGroup XNFS spec provides a simple mapping that is
|
||||
* independent of local errno values on the server and the client.
|
||||
*/
|
||||
static int decode_status(struct xdr_stream *xdr, struct mountres *res)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 status;
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_inline_decode(xdr, sizeof(status));
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
status = ntohl(*p);
|
||||
|
||||
for (i = 0; i <= ARRAY_SIZE(mnt_errtbl); i++) {
|
||||
if (mnt_errtbl[i].status == status) {
|
||||
res->errno = mnt_errtbl[i].errno;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dprintk("NFS: unrecognized MNT status code: %u\n", status);
|
||||
res->errno = -EACCES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res)
|
||||
{
|
||||
struct nfs_fh *fh = res->fh;
|
||||
__be32 *p;
|
||||
|
||||
if ((res->status = ntohl(*p++)) == 0) {
|
||||
fh->size = NFS2_FHSIZE;
|
||||
memcpy(fh->data, p, NFS2_FHSIZE);
|
||||
}
|
||||
p = xdr_inline_decode(xdr, NFS2_FHSIZE);
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
|
||||
fh->size = NFS2_FHSIZE;
|
||||
memcpy(fh->data, p, NFS2_FHSIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
|
||||
struct mnt_fhstatus *res)
|
||||
static int mnt_dec_mountres(struct rpc_rqst *req, __be32 *p,
|
||||
struct mountres *res)
|
||||
{
|
||||
struct xdr_stream xdr;
|
||||
int status;
|
||||
|
||||
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
|
||||
|
||||
status = decode_status(&xdr, res);
|
||||
if (unlikely(status != 0 || res->errno != 0))
|
||||
return status;
|
||||
return decode_fhandle(&xdr, res);
|
||||
}
|
||||
|
||||
static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 status;
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_inline_decode(xdr, sizeof(status));
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
status = ntohl(*p);
|
||||
|
||||
for (i = 0; i <= ARRAY_SIZE(mnt3_errtbl); i++) {
|
||||
if (mnt3_errtbl[i].status == status) {
|
||||
res->errno = mnt3_errtbl[i].errno;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dprintk("NFS: unrecognized MNT3 status code: %u\n", status);
|
||||
res->errno = -EACCES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res)
|
||||
{
|
||||
struct nfs_fh *fh = res->fh;
|
||||
unsigned size;
|
||||
u32 size;
|
||||
__be32 *p;
|
||||
|
||||
if ((res->status = ntohl(*p++)) == 0) {
|
||||
size = ntohl(*p++);
|
||||
if (size <= NFS3_FHSIZE && size != 0) {
|
||||
fh->size = size;
|
||||
memcpy(fh->data, p, size);
|
||||
} else
|
||||
res->status = -EBADHANDLE;
|
||||
}
|
||||
p = xdr_inline_decode(xdr, sizeof(size));
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
|
||||
size = ntohl(*p++);
|
||||
if (size > NFS3_FHSIZE || size == 0)
|
||||
return -EIO;
|
||||
|
||||
p = xdr_inline_decode(xdr, size);
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
|
||||
fh->size = size;
|
||||
memcpy(fh->data, p, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MNT_dirpath_sz (1 + 256)
|
||||
#define MNT_fhstatus_sz (1 + 8)
|
||||
#define MNT_fhstatus3_sz (1 + 16)
|
||||
static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
|
||||
{
|
||||
rpc_authflavor_t *flavors = res->auth_flavors;
|
||||
unsigned int *count = res->auth_count;
|
||||
u32 entries, i;
|
||||
__be32 *p;
|
||||
|
||||
if (*count == 0)
|
||||
return 0;
|
||||
|
||||
p = xdr_inline_decode(xdr, sizeof(entries));
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
entries = ntohl(*p);
|
||||
dprintk("NFS: received %u auth flavors\n", entries);
|
||||
if (entries > NFS_MAX_SECFLAVORS)
|
||||
entries = NFS_MAX_SECFLAVORS;
|
||||
|
||||
p = xdr_inline_decode(xdr, sizeof(u32) * entries);
|
||||
if (unlikely(p == NULL))
|
||||
return -EIO;
|
||||
|
||||
if (entries > *count)
|
||||
entries = *count;
|
||||
|
||||
for (i = 0; i < entries; i++) {
|
||||
flavors[i] = ntohl(*p++);
|
||||
dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]);
|
||||
}
|
||||
*count = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mnt_dec_mountres3(struct rpc_rqst *req, __be32 *p,
|
||||
struct mountres *res)
|
||||
{
|
||||
struct xdr_stream xdr;
|
||||
int status;
|
||||
|
||||
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
|
||||
|
||||
status = decode_fhs_status(&xdr, res);
|
||||
if (unlikely(status != 0 || res->errno != 0))
|
||||
return status;
|
||||
status = decode_fhandle3(&xdr, res);
|
||||
if (unlikely(status != 0)) {
|
||||
res->errno = -EBADHANDLE;
|
||||
return 0;
|
||||
}
|
||||
return decode_auth_flavors(&xdr, res);
|
||||
}
|
||||
|
||||
static struct rpc_procinfo mnt_procedures[] = {
|
||||
[MNTPROC_MNT] = {
|
||||
.p_proc = MNTPROC_MNT,
|
||||
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
|
||||
.p_decode = (kxdrproc_t) xdr_decode_fhstatus,
|
||||
.p_arglen = MNT_dirpath_sz,
|
||||
.p_replen = MNT_fhstatus_sz,
|
||||
.p_statidx = MNTPROC_MNT,
|
||||
[MOUNTPROC_MNT] = {
|
||||
.p_proc = MOUNTPROC_MNT,
|
||||
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
|
||||
.p_decode = (kxdrproc_t)mnt_dec_mountres,
|
||||
.p_arglen = MNT_enc_dirpath_sz,
|
||||
.p_replen = MNT_dec_mountres_sz,
|
||||
.p_statidx = MOUNTPROC_MNT,
|
||||
.p_name = "MOUNT",
|
||||
},
|
||||
};
|
||||
|
@ -159,10 +412,10 @@ static struct rpc_procinfo mnt_procedures[] = {
|
|||
static struct rpc_procinfo mnt3_procedures[] = {
|
||||
[MOUNTPROC3_MNT] = {
|
||||
.p_proc = MOUNTPROC3_MNT,
|
||||
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
|
||||
.p_decode = (kxdrproc_t) xdr_decode_fhstatus3,
|
||||
.p_arglen = MNT_dirpath_sz,
|
||||
.p_replen = MNT_fhstatus3_sz,
|
||||
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
|
||||
.p_decode = (kxdrproc_t)mnt_dec_mountres3,
|
||||
.p_arglen = MNT_enc_dirpath_sz,
|
||||
.p_replen = MNT_dec_mountres3_sz,
|
||||
.p_statidx = MOUNTPROC3_MNT,
|
||||
.p_name = "MOUNT",
|
||||
},
|
||||
|
|
|
@ -207,8 +207,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
|
|||
status = nfs_revalidate_inode(server, inode);
|
||||
if (status < 0)
|
||||
return ERR_PTR(status);
|
||||
if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
|
||||
nfs_zap_acl_cache(inode);
|
||||
acl = nfs3_get_cached_acl(inode, type);
|
||||
if (acl != ERR_PTR(-EAGAIN))
|
||||
return acl;
|
||||
|
|
|
@ -1173,16 +1173,30 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
|
|||
err = _nfs4_open_delegation_recall(ctx, state, stateid);
|
||||
switch (err) {
|
||||
case 0:
|
||||
return err;
|
||||
case -ENOENT:
|
||||
case -ESTALE:
|
||||
goto out;
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
case -NFS4ERR_EXPIRED:
|
||||
/* Don't recall a delegation if it was lost */
|
||||
nfs4_schedule_state_recovery(server->nfs_client);
|
||||
return err;
|
||||
goto out;
|
||||
case -ERESTARTSYS:
|
||||
/*
|
||||
* The show must go on: exit, but mark the
|
||||
* stateid as needing recovery.
|
||||
*/
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
||||
case -ENOMEM:
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
err = nfs4_handle_exception(server, err, &exception);
|
||||
} while (exception.retry);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -3238,8 +3252,6 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
|
|||
ret = nfs_revalidate_inode(server, inode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
|
||||
nfs_zap_acl_cache(inode);
|
||||
ret = nfs4_read_cached_acl(inode, buf, buflen);
|
||||
if (ret != -ENOENT)
|
||||
return ret;
|
||||
|
@ -3977,8 +3989,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
|
|||
ret = nfs4_wait_for_completion_rpc_task(task);
|
||||
if (ret == 0) {
|
||||
ret = data->rpc_status;
|
||||
if (ret == -NFS4ERR_DENIED)
|
||||
ret = -EAGAIN;
|
||||
} else
|
||||
data->cancelled = 1;
|
||||
rpc_put_task(task);
|
||||
|
@ -4066,9 +4076,11 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
|
|||
int err;
|
||||
|
||||
do {
|
||||
err = _nfs4_proc_setlk(state, cmd, request);
|
||||
if (err == -NFS4ERR_DENIED)
|
||||
err = -EAGAIN;
|
||||
err = nfs4_handle_exception(NFS_SERVER(state->inode),
|
||||
_nfs4_proc_setlk(state, cmd, request),
|
||||
&exception);
|
||||
err, &exception);
|
||||
} while (exception.retry);
|
||||
return err;
|
||||
}
|
||||
|
@ -4120,8 +4132,37 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
|
|||
goto out;
|
||||
do {
|
||||
err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
|
||||
if (err != -NFS4ERR_DELAY)
|
||||
break;
|
||||
switch (err) {
|
||||
default:
|
||||
printk(KERN_ERR "%s: unhandled error %d.\n",
|
||||
__func__, err);
|
||||
case 0:
|
||||
case -ESTALE:
|
||||
goto out;
|
||||
case -NFS4ERR_EXPIRED:
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
nfs4_schedule_state_recovery(server->nfs_client);
|
||||
goto out;
|
||||
case -ERESTARTSYS:
|
||||
/*
|
||||
* The show must go on: exit, but mark the
|
||||
* stateid as needing recovery.
|
||||
*/
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_OPENMODE:
|
||||
nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
|
||||
err = 0;
|
||||
goto out;
|
||||
case -ENOMEM:
|
||||
case -NFS4ERR_DENIED:
|
||||
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
||||
err = 0;
|
||||
goto out;
|
||||
case -NFS4ERR_DELAY:
|
||||
break;
|
||||
}
|
||||
err = nfs4_handle_exception(server, err, &exception);
|
||||
} while (exception.retry);
|
||||
out:
|
||||
|
|
|
@ -853,32 +853,45 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
|
|||
struct file_lock *fl;
|
||||
int status = 0;
|
||||
|
||||
if (inode->i_flock == NULL)
|
||||
return 0;
|
||||
|
||||
/* Guard against delegation returns and new lock/unlock calls */
|
||||
down_write(&nfsi->rwsem);
|
||||
/* Protect inode->i_flock using the BKL */
|
||||
lock_kernel();
|
||||
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||
continue;
|
||||
if (nfs_file_open_context(fl->fl_file)->state != state)
|
||||
continue;
|
||||
unlock_kernel();
|
||||
status = ops->recover_lock(state, fl);
|
||||
if (status >= 0)
|
||||
continue;
|
||||
switch (status) {
|
||||
case 0:
|
||||
break;
|
||||
case -ESTALE:
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_EXPIRED:
|
||||
case -NFS4ERR_NO_GRACE:
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
goto out;
|
||||
default:
|
||||
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
|
||||
__func__, status);
|
||||
case -NFS4ERR_EXPIRED:
|
||||
case -NFS4ERR_NO_GRACE:
|
||||
case -ENOMEM:
|
||||
case -NFS4ERR_DENIED:
|
||||
case -NFS4ERR_RECLAIM_BAD:
|
||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
||||
break;
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
goto out_err;
|
||||
status = 0;
|
||||
}
|
||||
lock_kernel();
|
||||
}
|
||||
up_write(&nfsi->rwsem);
|
||||
return 0;
|
||||
out_err:
|
||||
unlock_kernel();
|
||||
out:
|
||||
up_write(&nfsi->rwsem);
|
||||
return status;
|
||||
}
|
||||
|
@ -924,6 +937,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
|
|||
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
|
||||
__func__, status);
|
||||
case -ENOENT:
|
||||
case -ENOMEM:
|
||||
case -ESTALE:
|
||||
/*
|
||||
* Open state on this file cannot be recovered
|
||||
|
@ -934,6 +948,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
|
|||
/* Mark the file as being 'closed' */
|
||||
state->state = 0;
|
||||
break;
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_RECLAIM_BAD:
|
||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||
nfs4_state_mark_reclaim_nograce(sp->so_client, state);
|
||||
|
|
|
@ -92,6 +92,9 @@
|
|||
#undef NFSROOT_DEBUG
|
||||
#define NFSDBG_FACILITY NFSDBG_ROOT
|
||||
|
||||
/* Default port to use if server is not running a portmapper */
|
||||
#define NFS_MNT_PORT 627
|
||||
|
||||
/* Default path we try to mount. "%s" gets replaced by our IP address */
|
||||
#define NFS_ROOT "/tftpboot/%s"
|
||||
|
||||
|
@ -487,6 +490,7 @@ static int __init root_nfs_get_handle(void)
|
|||
{
|
||||
struct nfs_fh fh;
|
||||
struct sockaddr_in sin;
|
||||
unsigned int auth_flav_len = 0;
|
||||
struct nfs_mount_request request = {
|
||||
.sap = (struct sockaddr *)&sin,
|
||||
.salen = sizeof(sin),
|
||||
|
@ -496,6 +500,7 @@ static int __init root_nfs_get_handle(void)
|
|||
.protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
|
||||
XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
|
||||
.fh = &fh,
|
||||
.auth_flav_len = &auth_flav_len,
|
||||
};
|
||||
int status;
|
||||
|
||||
|
|
288
fs/nfs/super.c
288
fs/nfs/super.c
|
@ -140,22 +140,22 @@ static const match_table_t nfs_mount_option_tokens = {
|
|||
{ Opt_fscache_uniq, "fsc=%s" },
|
||||
{ Opt_nofscache, "nofsc" },
|
||||
|
||||
{ Opt_port, "port=%u" },
|
||||
{ Opt_rsize, "rsize=%u" },
|
||||
{ Opt_wsize, "wsize=%u" },
|
||||
{ Opt_bsize, "bsize=%u" },
|
||||
{ Opt_timeo, "timeo=%u" },
|
||||
{ Opt_retrans, "retrans=%u" },
|
||||
{ Opt_acregmin, "acregmin=%u" },
|
||||
{ Opt_acregmax, "acregmax=%u" },
|
||||
{ Opt_acdirmin, "acdirmin=%u" },
|
||||
{ Opt_acdirmax, "acdirmax=%u" },
|
||||
{ Opt_actimeo, "actimeo=%u" },
|
||||
{ Opt_namelen, "namlen=%u" },
|
||||
{ Opt_mountport, "mountport=%u" },
|
||||
{ Opt_mountvers, "mountvers=%u" },
|
||||
{ Opt_nfsvers, "nfsvers=%u" },
|
||||
{ Opt_nfsvers, "vers=%u" },
|
||||
{ Opt_port, "port=%s" },
|
||||
{ Opt_rsize, "rsize=%s" },
|
||||
{ Opt_wsize, "wsize=%s" },
|
||||
{ Opt_bsize, "bsize=%s" },
|
||||
{ Opt_timeo, "timeo=%s" },
|
||||
{ Opt_retrans, "retrans=%s" },
|
||||
{ Opt_acregmin, "acregmin=%s" },
|
||||
{ Opt_acregmax, "acregmax=%s" },
|
||||
{ Opt_acdirmin, "acdirmin=%s" },
|
||||
{ Opt_acdirmax, "acdirmax=%s" },
|
||||
{ Opt_actimeo, "actimeo=%s" },
|
||||
{ Opt_namelen, "namlen=%s" },
|
||||
{ Opt_mountport, "mountport=%s" },
|
||||
{ Opt_mountvers, "mountvers=%s" },
|
||||
{ Opt_nfsvers, "nfsvers=%s" },
|
||||
{ Opt_nfsvers, "vers=%s" },
|
||||
{ Opt_minorversion, "minorversion=%u" },
|
||||
|
||||
{ Opt_sec, "sec=%s" },
|
||||
|
@ -516,7 +516,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
|
|||
const char *nostr;
|
||||
} nfs_info[] = {
|
||||
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
|
||||
{ NFS_MOUNT_INTR, ",intr", ",nointr" },
|
||||
{ NFS_MOUNT_POSIX, ",posix", "" },
|
||||
{ NFS_MOUNT_NOCTO, ",nocto", "" },
|
||||
{ NFS_MOUNT_NOAC, ",noac", "" },
|
||||
|
@ -945,11 +944,6 @@ static int nfs_parse_security_flavors(char *value,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void nfs_parse_invalid_value(const char *option)
|
||||
{
|
||||
dfprintk(MOUNT, "NFS: bad value specified for %s option\n", option);
|
||||
}
|
||||
|
||||
/*
|
||||
* Error-check and convert a string of mount options from user space into
|
||||
* a data structure. The whole mount string is processed; bad options are
|
||||
|
@ -960,7 +954,7 @@ static int nfs_parse_mount_options(char *raw,
|
|||
struct nfs_parsed_mount_data *mnt)
|
||||
{
|
||||
char *p, *string, *secdata;
|
||||
int rc, sloppy = 0, errors = 0;
|
||||
int rc, sloppy = 0, invalid_option = 0;
|
||||
|
||||
if (!raw) {
|
||||
dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
|
||||
|
@ -984,7 +978,9 @@ static int nfs_parse_mount_options(char *raw,
|
|||
|
||||
while ((p = strsep(&raw, ",")) != NULL) {
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
int option, token;
|
||||
unsigned long option;
|
||||
int int_option;
|
||||
int token;
|
||||
|
||||
if (!*p)
|
||||
continue;
|
||||
|
@ -1093,114 +1089,156 @@ static int nfs_parse_mount_options(char *raw,
|
|||
* options that take numeric values
|
||||
*/
|
||||
case Opt_port:
|
||||
if (match_int(args, &option) ||
|
||||
option < 0 || option > USHORT_MAX) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("port");
|
||||
} else
|
||||
mnt->nfs_server.port = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0 || option > USHORT_MAX)
|
||||
goto out_invalid_value;
|
||||
mnt->nfs_server.port = option;
|
||||
break;
|
||||
case Opt_rsize:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("rsize");
|
||||
} else
|
||||
mnt->rsize = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->rsize = option;
|
||||
break;
|
||||
case Opt_wsize:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("wsize");
|
||||
} else
|
||||
mnt->wsize = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->wsize = option;
|
||||
break;
|
||||
case Opt_bsize:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("bsize");
|
||||
} else
|
||||
mnt->bsize = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->bsize = option;
|
||||
break;
|
||||
case Opt_timeo:
|
||||
if (match_int(args, &option) || option <= 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("timeo");
|
||||
} else
|
||||
mnt->timeo = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0 || option == 0)
|
||||
goto out_invalid_value;
|
||||
mnt->timeo = option;
|
||||
break;
|
||||
case Opt_retrans:
|
||||
if (match_int(args, &option) || option <= 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("retrans");
|
||||
} else
|
||||
mnt->retrans = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0 || option == 0)
|
||||
goto out_invalid_value;
|
||||
mnt->retrans = option;
|
||||
break;
|
||||
case Opt_acregmin:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("acregmin");
|
||||
} else
|
||||
mnt->acregmin = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->acregmin = option;
|
||||
break;
|
||||
case Opt_acregmax:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("acregmax");
|
||||
} else
|
||||
mnt->acregmax = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->acregmax = option;
|
||||
break;
|
||||
case Opt_acdirmin:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("acdirmin");
|
||||
} else
|
||||
mnt->acdirmin = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->acdirmin = option;
|
||||
break;
|
||||
case Opt_acdirmax:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("acdirmax");
|
||||
} else
|
||||
mnt->acdirmax = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->acdirmax = option;
|
||||
break;
|
||||
case Opt_actimeo:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("actimeo");
|
||||
} else
|
||||
mnt->acregmin = mnt->acregmax =
|
||||
mnt->acdirmin = mnt->acdirmax = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->acregmin = mnt->acregmax =
|
||||
mnt->acdirmin = mnt->acdirmax = option;
|
||||
break;
|
||||
case Opt_namelen:
|
||||
if (match_int(args, &option) || option < 0) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("namlen");
|
||||
} else
|
||||
mnt->namlen = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
mnt->namlen = option;
|
||||
break;
|
||||
case Opt_mountport:
|
||||
if (match_int(args, &option) ||
|
||||
option < 0 || option > USHORT_MAX) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("mountport");
|
||||
} else
|
||||
mnt->mount_server.port = option;
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0 || option > USHORT_MAX)
|
||||
goto out_invalid_value;
|
||||
mnt->mount_server.port = option;
|
||||
break;
|
||||
case Opt_mountvers:
|
||||
if (match_int(args, &option) ||
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0 ||
|
||||
option < NFS_MNT_VERSION ||
|
||||
option > NFS_MNT3_VERSION) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("mountvers");
|
||||
} else
|
||||
mnt->mount_server.version = option;
|
||||
option > NFS_MNT3_VERSION)
|
||||
goto out_invalid_value;
|
||||
mnt->mount_server.version = option;
|
||||
break;
|
||||
case Opt_nfsvers:
|
||||
if (match_int(args, &option)) {
|
||||
errors++;
|
||||
nfs_parse_invalid_value("nfsvers");
|
||||
break;
|
||||
}
|
||||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
rc = strict_strtoul(string, 10, &option);
|
||||
kfree(string);
|
||||
if (rc != 0)
|
||||
goto out_invalid_value;
|
||||
switch (option) {
|
||||
case NFS2_VERSION:
|
||||
mnt->flags &= ~NFS_MOUNT_VER3;
|
||||
|
@ -1209,16 +1247,15 @@ static int nfs_parse_mount_options(char *raw,
|
|||
mnt->flags |= NFS_MOUNT_VER3;
|
||||
break;
|
||||
default:
|
||||
errors++;
|
||||
nfs_parse_invalid_value("nfsvers");
|
||||
goto out_invalid_value;
|
||||
}
|
||||
break;
|
||||
case Opt_minorversion:
|
||||
if (match_int(args, &option))
|
||||
if (match_int(args, &int_option))
|
||||
return 0;
|
||||
if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
|
||||
if (int_option < 0 || int_option > NFS4_MAX_MINOR_VERSION)
|
||||
return 0;
|
||||
mnt->minorversion = option;
|
||||
mnt->minorversion = int_option;
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -1231,9 +1268,9 @@ static int nfs_parse_mount_options(char *raw,
|
|||
rc = nfs_parse_security_flavors(string, mnt);
|
||||
kfree(string);
|
||||
if (!rc) {
|
||||
errors++;
|
||||
dfprintk(MOUNT, "NFS: unrecognized "
|
||||
"security flavor\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case Opt_proto:
|
||||
|
@ -1247,23 +1284,25 @@ static int nfs_parse_mount_options(char *raw,
|
|||
case Opt_xprt_udp:
|
||||
mnt->flags &= ~NFS_MOUNT_TCP;
|
||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
|
||||
kfree(string);
|
||||
break;
|
||||
case Opt_xprt_tcp:
|
||||
mnt->flags |= NFS_MOUNT_TCP;
|
||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
|
||||
kfree(string);
|
||||
break;
|
||||
case Opt_xprt_rdma:
|
||||
/* vector side protocols to TCP */
|
||||
mnt->flags |= NFS_MOUNT_TCP;
|
||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
|
||||
xprt_load_transport(string);
|
||||
kfree(string);
|
||||
break;
|
||||
default:
|
||||
errors++;
|
||||
dfprintk(MOUNT, "NFS: unrecognized "
|
||||
"transport protocol\n");
|
||||
return 0;
|
||||
}
|
||||
kfree(string);
|
||||
break;
|
||||
case Opt_mountproto:
|
||||
string = match_strdup(args);
|
||||
|
@ -1282,9 +1321,9 @@ static int nfs_parse_mount_options(char *raw,
|
|||
break;
|
||||
case Opt_xprt_rdma: /* not used for side protocols */
|
||||
default:
|
||||
errors++;
|
||||
dfprintk(MOUNT, "NFS: unrecognized "
|
||||
"transport protocol\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case Opt_addr:
|
||||
|
@ -1340,9 +1379,9 @@ static int nfs_parse_mount_options(char *raw,
|
|||
mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
|
||||
break;
|
||||
default:
|
||||
errors++;
|
||||
dfprintk(MOUNT, "NFS: invalid "
|
||||
"lookupcache argument\n");
|
||||
return 0;
|
||||
};
|
||||
break;
|
||||
|
||||
|
@ -1360,20 +1399,20 @@ static int nfs_parse_mount_options(char *raw,
|
|||
break;
|
||||
|
||||
default:
|
||||
errors++;
|
||||
invalid_option = 1;
|
||||
dfprintk(MOUNT, "NFS: unrecognized mount option "
|
||||
"'%s'\n", p);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n",
|
||||
errors, (errors == 1 ? "" : "s"));
|
||||
if (!sloppy)
|
||||
return 0;
|
||||
}
|
||||
if (!sloppy && invalid_option)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
out_invalid_value:
|
||||
printk(KERN_INFO "NFS: bad mount option value specified: %s \n", p);
|
||||
return 0;
|
||||
out_nomem:
|
||||
printk(KERN_INFO "NFS: not enough memory to parse option\n");
|
||||
return 0;
|
||||
|
@ -1390,6 +1429,7 @@ static int nfs_parse_mount_options(char *raw,
|
|||
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||
struct nfs_fh *root_fh)
|
||||
{
|
||||
unsigned int auth_flavor_len = 0;
|
||||
struct nfs_mount_request request = {
|
||||
.sap = (struct sockaddr *)
|
||||
&args->mount_server.address,
|
||||
|
@ -1397,6 +1437,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
|||
.protocol = args->mount_server.protocol,
|
||||
.fh = root_fh,
|
||||
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
||||
.auth_flav_len = &auth_flavor_len,
|
||||
};
|
||||
int status;
|
||||
|
||||
|
@ -2249,6 +2290,11 @@ static void nfs4_fill_super(struct super_block *sb)
|
|||
nfs_initialise_sb(sb);
|
||||
}
|
||||
|
||||
static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
|
||||
{
|
||||
args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate NFSv4 mount options
|
||||
*/
|
||||
|
@ -2346,6 +2392,8 @@ static int nfs4_validate_mount_data(void *options,
|
|||
|
||||
nfs_validate_transport_protocol(args);
|
||||
|
||||
nfs4_validate_mount_flags(args);
|
||||
|
||||
if (args->auth_flavor_len > 1)
|
||||
goto out_inval_auth;
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ extern struct svc_procedure nlmsvc_procedures4[];
|
|||
extern int nlmsvc_grace_period;
|
||||
extern unsigned long nlmsvc_timeout;
|
||||
extern int nsm_use_hostnames;
|
||||
extern int nsm_local_state;
|
||||
extern u32 nsm_local_state;
|
||||
|
||||
/*
|
||||
* Lockd client functions
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
#define NFSMODE_SOCK 0140000
|
||||
#define NFSMODE_FIFO 0010000
|
||||
|
||||
#define NFS_MNT_PROGRAM 100005
|
||||
#define NFS_MNT_PORT 627
|
||||
#define NFS_MNT_PROGRAM 100005
|
||||
#define NFS_MNT_VERSION 1
|
||||
#define NFS_MNT3_VERSION 3
|
||||
|
||||
/*
|
||||
* NFS stats. The good thing with these values is that NFSv3 errors are
|
||||
|
|
|
@ -64,11 +64,4 @@ struct nfs2_fh {
|
|||
#define NFSPROC_READDIR 16
|
||||
#define NFSPROC_STATFS 17
|
||||
|
||||
#define NFS_MNT_PROGRAM 100005
|
||||
#define NFS_MNT_VERSION 1
|
||||
#define MNTPROC_NULL 0
|
||||
#define MNTPROC_MNT 1
|
||||
#define MNTPROC_UMNT 3
|
||||
#define MNTPROC_UMNTALL 4
|
||||
|
||||
#endif /* _LINUX_NFS2_H */
|
||||
|
|
|
@ -88,12 +88,7 @@ struct nfs3_fh {
|
|||
#define NFS3PROC_PATHCONF 20
|
||||
#define NFS3PROC_COMMIT 21
|
||||
|
||||
#define NFS_MNT3_PROGRAM 100005
|
||||
#define NFS_MNT3_VERSION 3
|
||||
#define MOUNTPROC3_NULL 0
|
||||
#define MOUNTPROC3_MNT 1
|
||||
#define MOUNTPROC3_UMNT 3
|
||||
#define MOUNTPROC3_UMNTALL 4
|
||||
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
|
|
|
@ -1965,6 +1965,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
|
|||
*/
|
||||
set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
|
||||
xprt_force_disconnect(xprt);
|
||||
break;
|
||||
case -ECONNREFUSED:
|
||||
case -ECONNRESET:
|
||||
case -ENETUNREACH:
|
||||
|
|
Loading…
Reference in a new issue