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;
|
struct nlm_lock *lock = &argp->lock;
|
||||||
|
|
||||||
nlmclnt_next_cookie(&argp->cookie);
|
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));
|
memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh));
|
||||||
lock->caller = utsname()->nodename;
|
lock->caller = utsname()->nodename;
|
||||||
lock->oh.data = req->a_owner;
|
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 */
|
/* Set up the argument struct */
|
||||||
nlmclnt_setlockargs(call, fl);
|
nlmclnt_setlockargs(call, fl);
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
|
if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
|
||||||
if (fl->fl_type != F_UNLCK) {
|
if (fl->fl_type != F_UNLCK) {
|
||||||
call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
|
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->fl_release_private(fl);
|
||||||
fl->fl_ops = NULL;
|
fl->fl_ops = NULL;
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
dprintk("lockd: clnt proc returns %d\n", status);
|
dprintk("lockd: clnt proc returns %d\n", status);
|
||||||
return status;
|
return status;
|
||||||
|
@ -519,6 +520,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
|
||||||
|
|
||||||
if (nsm_monitor(host) < 0)
|
if (nsm_monitor(host) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
req->a_args.state = nsm_local_state;
|
||||||
|
|
||||||
fl->fl_flags |= FL_ACCESS;
|
fl->fl_flags |= FL_ACCESS;
|
||||||
status = do_vfs_lock(fl);
|
status = do_vfs_lock(fl);
|
||||||
|
|
|
@ -53,7 +53,7 @@ static DEFINE_SPINLOCK(nsm_lock);
|
||||||
/*
|
/*
|
||||||
* Local NSM state
|
* Local NSM state
|
||||||
*/
|
*/
|
||||||
int __read_mostly nsm_local_state;
|
u32 __read_mostly nsm_local_state;
|
||||||
int __read_mostly nsm_use_hostnames;
|
int __read_mostly nsm_use_hostnames;
|
||||||
|
|
||||||
static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
|
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,
|
.program = &nsm_program,
|
||||||
.version = NSM_VERSION,
|
.version = NSM_VERSION,
|
||||||
.authflavor = RPC_AUTH_NULL,
|
.authflavor = RPC_AUTH_NULL,
|
||||||
|
.flags = RPC_CLNT_CREATE_NOPING,
|
||||||
};
|
};
|
||||||
|
|
||||||
return rpc_create(&args);
|
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;
|
nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
|
||||||
|
|
||||||
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
|
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res);
|
||||||
if (res.status != 0)
|
if (unlikely(res.status != 0))
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
if (status < 0)
|
if (unlikely(status < 0)) {
|
||||||
printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
|
printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
|
||||||
else
|
return status;
|
||||||
nsm->sm_monitored = 1;
|
}
|
||||||
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;
|
nfs_callback_tcpport6 = ret;
|
||||||
dprintk("NFS: Callback listener port = %u (af %u)\n",
|
dprintk("NFS: Callback listener port = %u (af %u)\n",
|
||||||
nfs_callback_tcpport6, PF_INET6);
|
nfs_callback_tcpport6, PF_INET6);
|
||||||
} else if (ret != -EAFNOSUPPORT)
|
} else if (ret == -EAFNOSUPPORT)
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
goto out_err;
|
goto out_err;
|
||||||
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
|
#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 nfs_client *clp;
|
||||||
struct rpc_cred *cred;
|
struct rpc_cred *cred;
|
||||||
|
int err = -ENOMEM;
|
||||||
|
|
||||||
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
|
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
|
||||||
goto error_0;
|
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;
|
clp->cl_addrlen = cl_init->addrlen;
|
||||||
|
|
||||||
if (cl_init->hostname) {
|
if (cl_init->hostname) {
|
||||||
|
err = -ENOMEM;
|
||||||
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
|
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
|
||||||
if (!clp->cl_hostname)
|
if (!clp->cl_hostname)
|
||||||
goto error_cleanup;
|
goto error_cleanup;
|
||||||
|
@ -159,7 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
|
||||||
error_cleanup:
|
error_cleanup:
|
||||||
kfree(clp);
|
kfree(clp);
|
||||||
error_0:
|
error_0:
|
||||||
return NULL;
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs4_shutdown_client(struct nfs_client *clp)
|
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);
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
new = nfs_alloc_client(cl_init);
|
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 a new client and return with it unready */
|
||||||
install_client:
|
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 inode *inode = state->inode;
|
||||||
struct file_lock *fl;
|
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) {
|
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||||
continue;
|
continue;
|
||||||
if (nfs_file_open_context(fl->fl_file) != ctx)
|
if (nfs_file_open_context(fl->fl_file) != ctx)
|
||||||
continue;
|
continue;
|
||||||
|
unlock_kernel();
|
||||||
status = nfs4_lock_delegation_recall(state, fl);
|
status = nfs4_lock_delegation_recall(state, fl);
|
||||||
if (status >= 0)
|
if (status < 0)
|
||||||
continue;
|
goto out;
|
||||||
switch (status) {
|
lock_kernel();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
unlock_kernel();
|
||||||
out_err:
|
out:
|
||||||
return status;
|
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);
|
struct nfs_inode *nfsi = NFS_I(inode);
|
||||||
|
|
||||||
nfs_msync_inode(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);
|
down_write(&nfsi->rwsem);
|
||||||
nfs_delegation_claim_opens(inode, &delegation->stateid);
|
nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||||
up_write(&nfsi->rwsem);
|
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);
|
size_t count, unsigned int flags);
|
||||||
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
|
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
|
||||||
unsigned long nr_segs, loff_t pos);
|
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,
|
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
|
||||||
unsigned long nr_segs, loff_t pos);
|
unsigned long nr_segs, loff_t pos);
|
||||||
static int nfs_file_flush(struct file *, fl_owner_t id);
|
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,
|
.lock = nfs_lock,
|
||||||
.flock = nfs_flock,
|
.flock = nfs_flock,
|
||||||
.splice_read = nfs_file_splice_read,
|
.splice_read = nfs_file_splice_read,
|
||||||
|
.splice_write = nfs_file_splice_write,
|
||||||
.check_flags = nfs_check_flags,
|
.check_flags = nfs_check_flags,
|
||||||
.setlease = nfs_setlease,
|
.setlease = nfs_setlease,
|
||||||
};
|
};
|
||||||
|
@ -587,12 +591,38 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
goto out;
|
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)
|
static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
|
||||||
{
|
{
|
||||||
struct inode *inode = filp->f_mapping->host;
|
struct inode *inode = filp->f_mapping->host;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
/* Try local locking first */
|
/* Try local locking first */
|
||||||
posix_test_lock(filp, fl);
|
posix_test_lock(filp, fl);
|
||||||
if (fl->fl_type != F_UNLCK) {
|
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);
|
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return status;
|
return status;
|
||||||
out_noconflict:
|
out_noconflict:
|
||||||
fl->fl_type = F_UNLCK;
|
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
|
* If we're signalled while cleaning up locks on process exit, we
|
||||||
* still need to complete the unlock.
|
* still need to complete the unlock.
|
||||||
*/
|
*/
|
||||||
lock_kernel();
|
|
||||||
/* Use local locking if mounted with "-onolock" */
|
/* Use local locking if mounted with "-onolock" */
|
||||||
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
||||||
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||||
else
|
else
|
||||||
status = do_vfs_lock(filp, fl);
|
status = do_vfs_lock(filp, fl);
|
||||||
unlock_kernel();
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,13 +700,11 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
/* Use local locking if mounted with "-onolock" */
|
/* Use local locking if mounted with "-onolock" */
|
||||||
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
|
||||||
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
|
||||||
else
|
else
|
||||||
status = do_vfs_lock(filp, fl);
|
status = do_vfs_lock(filp, fl);
|
||||||
unlock_kernel();
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out;
|
goto out;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -42,6 +42,12 @@ struct nfs_clone_mount {
|
||||||
rpc_authflavor_t authflavor;
|
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
|
* In-kernel mount arguments
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +97,8 @@ struct nfs_mount_request {
|
||||||
unsigned short protocol;
|
unsigned short protocol;
|
||||||
struct nfs_fh *fh;
|
struct nfs_fh *fh;
|
||||||
int noresvport;
|
int noresvport;
|
||||||
|
unsigned int *auth_flav_len;
|
||||||
|
rpc_authflavor_t *auth_flavs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int nfs_mount(struct nfs_mount_request *info);
|
extern int nfs_mount(struct nfs_mount_request *info);
|
||||||
|
|
|
@ -20,8 +20,116 @@
|
||||||
# define NFSDBG_FACILITY NFSDBG_MOUNT
|
# define NFSDBG_FACILITY NFSDBG_MOUNT
|
||||||
#endif
|
#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;
|
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 {
|
struct mnt_fhstatus {
|
||||||
u32 status;
|
u32 status;
|
||||||
struct nfs_fh *fh;
|
struct nfs_fh *fh;
|
||||||
|
@ -35,8 +143,10 @@ struct mnt_fhstatus {
|
||||||
*/
|
*/
|
||||||
int nfs_mount(struct nfs_mount_request *info)
|
int nfs_mount(struct nfs_mount_request *info)
|
||||||
{
|
{
|
||||||
struct mnt_fhstatus result = {
|
struct mountres result = {
|
||||||
.fh = info->fh
|
.fh = info->fh,
|
||||||
|
.auth_count = info->auth_flav_len,
|
||||||
|
.auth_flavors = info->auth_flavs,
|
||||||
};
|
};
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_argp = info->dirpath,
|
.rpc_argp = info->dirpath,
|
||||||
|
@ -68,14 +178,14 @@ int nfs_mount(struct nfs_mount_request *info)
|
||||||
if (info->version == NFS_MNT3_VERSION)
|
if (info->version == NFS_MNT3_VERSION)
|
||||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
|
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
|
||||||
else
|
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);
|
status = rpc_call_sync(mnt_clnt, &msg, 0);
|
||||||
rpc_shutdown_client(mnt_clnt);
|
rpc_shutdown_client(mnt_clnt);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out_call_err;
|
goto out_call_err;
|
||||||
if (result.status != 0)
|
if (result.errno != 0)
|
||||||
goto out_mnt_err;
|
goto out_mnt_err;
|
||||||
|
|
||||||
dprintk("NFS: MNT request succeeded\n");
|
dprintk("NFS: MNT request succeeded\n");
|
||||||
|
@ -86,72 +196,215 @@ int nfs_mount(struct nfs_mount_request *info)
|
||||||
|
|
||||||
out_clnt_err:
|
out_clnt_err:
|
||||||
status = PTR_ERR(mnt_clnt);
|
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;
|
goto out;
|
||||||
|
|
||||||
out_call_err:
|
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;
|
goto out;
|
||||||
|
|
||||||
out_mnt_err:
|
out_mnt_err:
|
||||||
dprintk("NFS: MNT server returned result %d\n", result.status);
|
dprintk("NFS: MNT server returned result %d\n", result.errno);
|
||||||
status = nfs_stat_to_errno(result.status);
|
status = result.errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XDR encode/decode functions for MOUNT
|
* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
|
static int mnt_enc_dirpath(struct rpc_rqst *req, __be32 *p,
|
||||||
struct mnt_fhstatus *res)
|
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;
|
struct nfs_fh *fh = res->fh;
|
||||||
|
__be32 *p;
|
||||||
|
|
||||||
if ((res->status = ntohl(*p++)) == 0) {
|
p = xdr_inline_decode(xdr, NFS2_FHSIZE);
|
||||||
fh->size = NFS2_FHSIZE;
|
if (unlikely(p == NULL))
|
||||||
memcpy(fh->data, p, NFS2_FHSIZE);
|
return -EIO;
|
||||||
}
|
|
||||||
|
fh->size = NFS2_FHSIZE;
|
||||||
|
memcpy(fh->data, p, NFS2_FHSIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
|
static int mnt_dec_mountres(struct rpc_rqst *req, __be32 *p,
|
||||||
struct mnt_fhstatus *res)
|
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;
|
struct nfs_fh *fh = res->fh;
|
||||||
unsigned size;
|
u32 size;
|
||||||
|
__be32 *p;
|
||||||
|
|
||||||
if ((res->status = ntohl(*p++)) == 0) {
|
p = xdr_inline_decode(xdr, sizeof(size));
|
||||||
size = ntohl(*p++);
|
if (unlikely(p == NULL))
|
||||||
if (size <= NFS3_FHSIZE && size != 0) {
|
return -EIO;
|
||||||
fh->size = size;
|
|
||||||
memcpy(fh->data, p, size);
|
size = ntohl(*p++);
|
||||||
} else
|
if (size > NFS3_FHSIZE || size == 0)
|
||||||
res->status = -EBADHANDLE;
|
return -EIO;
|
||||||
}
|
|
||||||
|
p = xdr_inline_decode(xdr, size);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
fh->size = size;
|
||||||
|
memcpy(fh->data, p, size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MNT_dirpath_sz (1 + 256)
|
static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
|
||||||
#define MNT_fhstatus_sz (1 + 8)
|
{
|
||||||
#define MNT_fhstatus3_sz (1 + 16)
|
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[] = {
|
static struct rpc_procinfo mnt_procedures[] = {
|
||||||
[MNTPROC_MNT] = {
|
[MOUNTPROC_MNT] = {
|
||||||
.p_proc = MNTPROC_MNT,
|
.p_proc = MOUNTPROC_MNT,
|
||||||
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
|
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
|
||||||
.p_decode = (kxdrproc_t) xdr_decode_fhstatus,
|
.p_decode = (kxdrproc_t)mnt_dec_mountres,
|
||||||
.p_arglen = MNT_dirpath_sz,
|
.p_arglen = MNT_enc_dirpath_sz,
|
||||||
.p_replen = MNT_fhstatus_sz,
|
.p_replen = MNT_dec_mountres_sz,
|
||||||
.p_statidx = MNTPROC_MNT,
|
.p_statidx = MOUNTPROC_MNT,
|
||||||
.p_name = "MOUNT",
|
.p_name = "MOUNT",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -159,10 +412,10 @@ static struct rpc_procinfo mnt_procedures[] = {
|
||||||
static struct rpc_procinfo mnt3_procedures[] = {
|
static struct rpc_procinfo mnt3_procedures[] = {
|
||||||
[MOUNTPROC3_MNT] = {
|
[MOUNTPROC3_MNT] = {
|
||||||
.p_proc = MOUNTPROC3_MNT,
|
.p_proc = MOUNTPROC3_MNT,
|
||||||
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
|
.p_encode = (kxdrproc_t)mnt_enc_dirpath,
|
||||||
.p_decode = (kxdrproc_t) xdr_decode_fhstatus3,
|
.p_decode = (kxdrproc_t)mnt_dec_mountres3,
|
||||||
.p_arglen = MNT_dirpath_sz,
|
.p_arglen = MNT_enc_dirpath_sz,
|
||||||
.p_replen = MNT_fhstatus3_sz,
|
.p_replen = MNT_dec_mountres3_sz,
|
||||||
.p_statidx = MOUNTPROC3_MNT,
|
.p_statidx = MOUNTPROC3_MNT,
|
||||||
.p_name = "MOUNT",
|
.p_name = "MOUNT",
|
||||||
},
|
},
|
||||||
|
|
|
@ -207,8 +207,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
|
||||||
status = nfs_revalidate_inode(server, inode);
|
status = nfs_revalidate_inode(server, inode);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return ERR_PTR(status);
|
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);
|
acl = nfs3_get_cached_acl(inode, type);
|
||||||
if (acl != ERR_PTR(-EAGAIN))
|
if (acl != ERR_PTR(-EAGAIN))
|
||||||
return acl;
|
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);
|
err = _nfs4_open_delegation_recall(ctx, state, stateid);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 0:
|
case 0:
|
||||||
return err;
|
case -ENOENT:
|
||||||
|
case -ESTALE:
|
||||||
|
goto out;
|
||||||
case -NFS4ERR_STALE_CLIENTID:
|
case -NFS4ERR_STALE_CLIENTID:
|
||||||
case -NFS4ERR_STALE_STATEID:
|
case -NFS4ERR_STALE_STATEID:
|
||||||
case -NFS4ERR_EXPIRED:
|
case -NFS4ERR_EXPIRED:
|
||||||
/* Don't recall a delegation if it was lost */
|
/* Don't recall a delegation if it was lost */
|
||||||
nfs4_schedule_state_recovery(server->nfs_client);
|
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);
|
err = nfs4_handle_exception(server, err, &exception);
|
||||||
} while (exception.retry);
|
} while (exception.retry);
|
||||||
|
out:
|
||||||
return err;
|
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);
|
ret = nfs_revalidate_inode(server, inode);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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);
|
ret = nfs4_read_cached_acl(inode, buf, buflen);
|
||||||
if (ret != -ENOENT)
|
if (ret != -ENOENT)
|
||||||
return ret;
|
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);
|
ret = nfs4_wait_for_completion_rpc_task(task);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = data->rpc_status;
|
ret = data->rpc_status;
|
||||||
if (ret == -NFS4ERR_DENIED)
|
|
||||||
ret = -EAGAIN;
|
|
||||||
} else
|
} else
|
||||||
data->cancelled = 1;
|
data->cancelled = 1;
|
||||||
rpc_put_task(task);
|
rpc_put_task(task);
|
||||||
|
@ -4066,9 +4076,11 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
err = _nfs4_proc_setlk(state, cmd, request);
|
||||||
|
if (err == -NFS4ERR_DENIED)
|
||||||
|
err = -EAGAIN;
|
||||||
err = nfs4_handle_exception(NFS_SERVER(state->inode),
|
err = nfs4_handle_exception(NFS_SERVER(state->inode),
|
||||||
_nfs4_proc_setlk(state, cmd, request),
|
err, &exception);
|
||||||
&exception);
|
|
||||||
} while (exception.retry);
|
} while (exception.retry);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -4120,8 +4132,37 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
|
||||||
goto out;
|
goto out;
|
||||||
do {
|
do {
|
||||||
err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
|
err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
|
||||||
if (err != -NFS4ERR_DELAY)
|
switch (err) {
|
||||||
break;
|
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);
|
err = nfs4_handle_exception(server, err, &exception);
|
||||||
} while (exception.retry);
|
} while (exception.retry);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -853,32 +853,45 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
|
||||||
struct file_lock *fl;
|
struct file_lock *fl;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
if (inode->i_flock == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Guard against delegation returns and new lock/unlock calls */
|
||||||
down_write(&nfsi->rwsem);
|
down_write(&nfsi->rwsem);
|
||||||
|
/* Protect inode->i_flock using the BKL */
|
||||||
|
lock_kernel();
|
||||||
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||||
continue;
|
continue;
|
||||||
if (nfs_file_open_context(fl->fl_file)->state != state)
|
if (nfs_file_open_context(fl->fl_file)->state != state)
|
||||||
continue;
|
continue;
|
||||||
|
unlock_kernel();
|
||||||
status = ops->recover_lock(state, fl);
|
status = ops->recover_lock(state, fl);
|
||||||
if (status >= 0)
|
|
||||||
continue;
|
|
||||||
switch (status) {
|
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:
|
default:
|
||||||
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
|
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
|
||||||
__func__, status);
|
__func__, status);
|
||||||
case -NFS4ERR_EXPIRED:
|
case -ENOMEM:
|
||||||
case -NFS4ERR_NO_GRACE:
|
case -NFS4ERR_DENIED:
|
||||||
case -NFS4ERR_RECLAIM_BAD:
|
case -NFS4ERR_RECLAIM_BAD:
|
||||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||||
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
||||||
break;
|
status = 0;
|
||||||
case -NFS4ERR_STALE_CLIENTID:
|
|
||||||
goto out_err;
|
|
||||||
}
|
}
|
||||||
|
lock_kernel();
|
||||||
}
|
}
|
||||||
up_write(&nfsi->rwsem);
|
unlock_kernel();
|
||||||
return 0;
|
out:
|
||||||
out_err:
|
|
||||||
up_write(&nfsi->rwsem);
|
up_write(&nfsi->rwsem);
|
||||||
return status;
|
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",
|
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
|
||||||
__func__, status);
|
__func__, status);
|
||||||
case -ENOENT:
|
case -ENOENT:
|
||||||
|
case -ENOMEM:
|
||||||
case -ESTALE:
|
case -ESTALE:
|
||||||
/*
|
/*
|
||||||
* Open state on this file cannot be recovered
|
* 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' */
|
/* Mark the file as being 'closed' */
|
||||||
state->state = 0;
|
state->state = 0;
|
||||||
break;
|
break;
|
||||||
|
case -NFS4ERR_ADMIN_REVOKED:
|
||||||
|
case -NFS4ERR_STALE_STATEID:
|
||||||
|
case -NFS4ERR_BAD_STATEID:
|
||||||
case -NFS4ERR_RECLAIM_BAD:
|
case -NFS4ERR_RECLAIM_BAD:
|
||||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||||
nfs4_state_mark_reclaim_nograce(sp->so_client, state);
|
nfs4_state_mark_reclaim_nograce(sp->so_client, state);
|
||||||
|
|
|
@ -92,6 +92,9 @@
|
||||||
#undef NFSROOT_DEBUG
|
#undef NFSROOT_DEBUG
|
||||||
#define NFSDBG_FACILITY NFSDBG_ROOT
|
#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 */
|
/* Default path we try to mount. "%s" gets replaced by our IP address */
|
||||||
#define NFS_ROOT "/tftpboot/%s"
|
#define NFS_ROOT "/tftpboot/%s"
|
||||||
|
|
||||||
|
@ -487,6 +490,7 @@ static int __init root_nfs_get_handle(void)
|
||||||
{
|
{
|
||||||
struct nfs_fh fh;
|
struct nfs_fh fh;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
unsigned int auth_flav_len = 0;
|
||||||
struct nfs_mount_request request = {
|
struct nfs_mount_request request = {
|
||||||
.sap = (struct sockaddr *)&sin,
|
.sap = (struct sockaddr *)&sin,
|
||||||
.salen = sizeof(sin),
|
.salen = sizeof(sin),
|
||||||
|
@ -496,6 +500,7 @@ static int __init root_nfs_get_handle(void)
|
||||||
.protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
|
.protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
|
||||||
XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
|
XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
|
||||||
.fh = &fh,
|
.fh = &fh,
|
||||||
|
.auth_flav_len = &auth_flav_len,
|
||||||
};
|
};
|
||||||
int status;
|
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_fscache_uniq, "fsc=%s" },
|
||||||
{ Opt_nofscache, "nofsc" },
|
{ Opt_nofscache, "nofsc" },
|
||||||
|
|
||||||
{ Opt_port, "port=%u" },
|
{ Opt_port, "port=%s" },
|
||||||
{ Opt_rsize, "rsize=%u" },
|
{ Opt_rsize, "rsize=%s" },
|
||||||
{ Opt_wsize, "wsize=%u" },
|
{ Opt_wsize, "wsize=%s" },
|
||||||
{ Opt_bsize, "bsize=%u" },
|
{ Opt_bsize, "bsize=%s" },
|
||||||
{ Opt_timeo, "timeo=%u" },
|
{ Opt_timeo, "timeo=%s" },
|
||||||
{ Opt_retrans, "retrans=%u" },
|
{ Opt_retrans, "retrans=%s" },
|
||||||
{ Opt_acregmin, "acregmin=%u" },
|
{ Opt_acregmin, "acregmin=%s" },
|
||||||
{ Opt_acregmax, "acregmax=%u" },
|
{ Opt_acregmax, "acregmax=%s" },
|
||||||
{ Opt_acdirmin, "acdirmin=%u" },
|
{ Opt_acdirmin, "acdirmin=%s" },
|
||||||
{ Opt_acdirmax, "acdirmax=%u" },
|
{ Opt_acdirmax, "acdirmax=%s" },
|
||||||
{ Opt_actimeo, "actimeo=%u" },
|
{ Opt_actimeo, "actimeo=%s" },
|
||||||
{ Opt_namelen, "namlen=%u" },
|
{ Opt_namelen, "namlen=%s" },
|
||||||
{ Opt_mountport, "mountport=%u" },
|
{ Opt_mountport, "mountport=%s" },
|
||||||
{ Opt_mountvers, "mountvers=%u" },
|
{ Opt_mountvers, "mountvers=%s" },
|
||||||
{ Opt_nfsvers, "nfsvers=%u" },
|
{ Opt_nfsvers, "nfsvers=%s" },
|
||||||
{ Opt_nfsvers, "vers=%u" },
|
{ Opt_nfsvers, "vers=%s" },
|
||||||
{ Opt_minorversion, "minorversion=%u" },
|
{ Opt_minorversion, "minorversion=%u" },
|
||||||
|
|
||||||
{ Opt_sec, "sec=%s" },
|
{ 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;
|
const char *nostr;
|
||||||
} nfs_info[] = {
|
} nfs_info[] = {
|
||||||
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
|
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
|
||||||
{ NFS_MOUNT_INTR, ",intr", ",nointr" },
|
|
||||||
{ NFS_MOUNT_POSIX, ",posix", "" },
|
{ NFS_MOUNT_POSIX, ",posix", "" },
|
||||||
{ NFS_MOUNT_NOCTO, ",nocto", "" },
|
{ NFS_MOUNT_NOCTO, ",nocto", "" },
|
||||||
{ NFS_MOUNT_NOAC, ",noac", "" },
|
{ NFS_MOUNT_NOAC, ",noac", "" },
|
||||||
|
@ -945,11 +944,6 @@ static int nfs_parse_security_flavors(char *value,
|
||||||
return 1;
|
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
|
* 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
|
* 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)
|
struct nfs_parsed_mount_data *mnt)
|
||||||
{
|
{
|
||||||
char *p, *string, *secdata;
|
char *p, *string, *secdata;
|
||||||
int rc, sloppy = 0, errors = 0;
|
int rc, sloppy = 0, invalid_option = 0;
|
||||||
|
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
|
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) {
|
while ((p = strsep(&raw, ",")) != NULL) {
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
int option, token;
|
unsigned long option;
|
||||||
|
int int_option;
|
||||||
|
int token;
|
||||||
|
|
||||||
if (!*p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1093,114 +1089,156 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
* options that take numeric values
|
* options that take numeric values
|
||||||
*/
|
*/
|
||||||
case Opt_port:
|
case Opt_port:
|
||||||
if (match_int(args, &option) ||
|
string = match_strdup(args);
|
||||||
option < 0 || option > USHORT_MAX) {
|
if (string == NULL)
|
||||||
errors++;
|
goto out_nomem;
|
||||||
nfs_parse_invalid_value("port");
|
rc = strict_strtoul(string, 10, &option);
|
||||||
} else
|
kfree(string);
|
||||||
mnt->nfs_server.port = option;
|
if (rc != 0 || option > USHORT_MAX)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->nfs_server.port = option;
|
||||||
break;
|
break;
|
||||||
case Opt_rsize:
|
case Opt_rsize:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("rsize");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->rsize = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->rsize = option;
|
||||||
break;
|
break;
|
||||||
case Opt_wsize:
|
case Opt_wsize:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("wsize");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->wsize = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->wsize = option;
|
||||||
break;
|
break;
|
||||||
case Opt_bsize:
|
case Opt_bsize:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("bsize");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->bsize = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->bsize = option;
|
||||||
break;
|
break;
|
||||||
case Opt_timeo:
|
case Opt_timeo:
|
||||||
if (match_int(args, &option) || option <= 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("timeo");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->timeo = option;
|
kfree(string);
|
||||||
|
if (rc != 0 || option == 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->timeo = option;
|
||||||
break;
|
break;
|
||||||
case Opt_retrans:
|
case Opt_retrans:
|
||||||
if (match_int(args, &option) || option <= 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("retrans");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->retrans = option;
|
kfree(string);
|
||||||
|
if (rc != 0 || option == 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->retrans = option;
|
||||||
break;
|
break;
|
||||||
case Opt_acregmin:
|
case Opt_acregmin:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("acregmin");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->acregmin = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->acregmin = option;
|
||||||
break;
|
break;
|
||||||
case Opt_acregmax:
|
case Opt_acregmax:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("acregmax");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->acregmax = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->acregmax = option;
|
||||||
break;
|
break;
|
||||||
case Opt_acdirmin:
|
case Opt_acdirmin:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("acdirmin");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->acdirmin = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->acdirmin = option;
|
||||||
break;
|
break;
|
||||||
case Opt_acdirmax:
|
case Opt_acdirmax:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("acdirmax");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->acdirmax = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->acdirmax = option;
|
||||||
break;
|
break;
|
||||||
case Opt_actimeo:
|
case Opt_actimeo:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("actimeo");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->acregmin = mnt->acregmax =
|
kfree(string);
|
||||||
mnt->acdirmin = mnt->acdirmax = option;
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->acregmin = mnt->acregmax =
|
||||||
|
mnt->acdirmin = mnt->acdirmax = option;
|
||||||
break;
|
break;
|
||||||
case Opt_namelen:
|
case Opt_namelen:
|
||||||
if (match_int(args, &option) || option < 0) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("namlen");
|
goto out_nomem;
|
||||||
} else
|
rc = strict_strtoul(string, 10, &option);
|
||||||
mnt->namlen = option;
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->namlen = option;
|
||||||
break;
|
break;
|
||||||
case Opt_mountport:
|
case Opt_mountport:
|
||||||
if (match_int(args, &option) ||
|
string = match_strdup(args);
|
||||||
option < 0 || option > USHORT_MAX) {
|
if (string == NULL)
|
||||||
errors++;
|
goto out_nomem;
|
||||||
nfs_parse_invalid_value("mountport");
|
rc = strict_strtoul(string, 10, &option);
|
||||||
} else
|
kfree(string);
|
||||||
mnt->mount_server.port = option;
|
if (rc != 0 || option > USHORT_MAX)
|
||||||
|
goto out_invalid_value;
|
||||||
|
mnt->mount_server.port = option;
|
||||||
break;
|
break;
|
||||||
case Opt_mountvers:
|
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_MNT_VERSION ||
|
||||||
option > NFS_MNT3_VERSION) {
|
option > NFS_MNT3_VERSION)
|
||||||
errors++;
|
goto out_invalid_value;
|
||||||
nfs_parse_invalid_value("mountvers");
|
mnt->mount_server.version = option;
|
||||||
} else
|
|
||||||
mnt->mount_server.version = option;
|
|
||||||
break;
|
break;
|
||||||
case Opt_nfsvers:
|
case Opt_nfsvers:
|
||||||
if (match_int(args, &option)) {
|
string = match_strdup(args);
|
||||||
errors++;
|
if (string == NULL)
|
||||||
nfs_parse_invalid_value("nfsvers");
|
goto out_nomem;
|
||||||
break;
|
rc = strict_strtoul(string, 10, &option);
|
||||||
}
|
kfree(string);
|
||||||
|
if (rc != 0)
|
||||||
|
goto out_invalid_value;
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case NFS2_VERSION:
|
case NFS2_VERSION:
|
||||||
mnt->flags &= ~NFS_MOUNT_VER3;
|
mnt->flags &= ~NFS_MOUNT_VER3;
|
||||||
|
@ -1209,16 +1247,15 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
mnt->flags |= NFS_MOUNT_VER3;
|
mnt->flags |= NFS_MOUNT_VER3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errors++;
|
goto out_invalid_value;
|
||||||
nfs_parse_invalid_value("nfsvers");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_minorversion:
|
case Opt_minorversion:
|
||||||
if (match_int(args, &option))
|
if (match_int(args, &int_option))
|
||||||
return 0;
|
return 0;
|
||||||
if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
|
if (int_option < 0 || int_option > NFS4_MAX_MINOR_VERSION)
|
||||||
return 0;
|
return 0;
|
||||||
mnt->minorversion = option;
|
mnt->minorversion = int_option;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1231,9 +1268,9 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
rc = nfs_parse_security_flavors(string, mnt);
|
rc = nfs_parse_security_flavors(string, mnt);
|
||||||
kfree(string);
|
kfree(string);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
errors++;
|
|
||||||
dfprintk(MOUNT, "NFS: unrecognized "
|
dfprintk(MOUNT, "NFS: unrecognized "
|
||||||
"security flavor\n");
|
"security flavor\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_proto:
|
case Opt_proto:
|
||||||
|
@ -1247,23 +1284,25 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
case Opt_xprt_udp:
|
case Opt_xprt_udp:
|
||||||
mnt->flags &= ~NFS_MOUNT_TCP;
|
mnt->flags &= ~NFS_MOUNT_TCP;
|
||||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
|
mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
|
||||||
|
kfree(string);
|
||||||
break;
|
break;
|
||||||
case Opt_xprt_tcp:
|
case Opt_xprt_tcp:
|
||||||
mnt->flags |= NFS_MOUNT_TCP;
|
mnt->flags |= NFS_MOUNT_TCP;
|
||||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
|
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
|
||||||
|
kfree(string);
|
||||||
break;
|
break;
|
||||||
case Opt_xprt_rdma:
|
case Opt_xprt_rdma:
|
||||||
/* vector side protocols to TCP */
|
/* vector side protocols to TCP */
|
||||||
mnt->flags |= NFS_MOUNT_TCP;
|
mnt->flags |= NFS_MOUNT_TCP;
|
||||||
mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
|
mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
|
||||||
xprt_load_transport(string);
|
xprt_load_transport(string);
|
||||||
|
kfree(string);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errors++;
|
|
||||||
dfprintk(MOUNT, "NFS: unrecognized "
|
dfprintk(MOUNT, "NFS: unrecognized "
|
||||||
"transport protocol\n");
|
"transport protocol\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
kfree(string);
|
|
||||||
break;
|
break;
|
||||||
case Opt_mountproto:
|
case Opt_mountproto:
|
||||||
string = match_strdup(args);
|
string = match_strdup(args);
|
||||||
|
@ -1282,9 +1321,9 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
break;
|
break;
|
||||||
case Opt_xprt_rdma: /* not used for side protocols */
|
case Opt_xprt_rdma: /* not used for side protocols */
|
||||||
default:
|
default:
|
||||||
errors++;
|
|
||||||
dfprintk(MOUNT, "NFS: unrecognized "
|
dfprintk(MOUNT, "NFS: unrecognized "
|
||||||
"transport protocol\n");
|
"transport protocol\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_addr:
|
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;
|
mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errors++;
|
|
||||||
dfprintk(MOUNT, "NFS: invalid "
|
dfprintk(MOUNT, "NFS: invalid "
|
||||||
"lookupcache argument\n");
|
"lookupcache argument\n");
|
||||||
|
return 0;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1360,20 +1399,20 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errors++;
|
invalid_option = 1;
|
||||||
dfprintk(MOUNT, "NFS: unrecognized mount option "
|
dfprintk(MOUNT, "NFS: unrecognized mount option "
|
||||||
"'%s'\n", p);
|
"'%s'\n", p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors > 0) {
|
if (!sloppy && invalid_option)
|
||||||
dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n",
|
return 0;
|
||||||
errors, (errors == 1 ? "" : "s"));
|
|
||||||
if (!sloppy)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
out_invalid_value:
|
||||||
|
printk(KERN_INFO "NFS: bad mount option value specified: %s \n", p);
|
||||||
|
return 0;
|
||||||
out_nomem:
|
out_nomem:
|
||||||
printk(KERN_INFO "NFS: not enough memory to parse option\n");
|
printk(KERN_INFO "NFS: not enough memory to parse option\n");
|
||||||
return 0;
|
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,
|
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
struct nfs_fh *root_fh)
|
struct nfs_fh *root_fh)
|
||||||
{
|
{
|
||||||
|
unsigned int auth_flavor_len = 0;
|
||||||
struct nfs_mount_request request = {
|
struct nfs_mount_request request = {
|
||||||
.sap = (struct sockaddr *)
|
.sap = (struct sockaddr *)
|
||||||
&args->mount_server.address,
|
&args->mount_server.address,
|
||||||
|
@ -1397,6 +1437,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
.protocol = args->mount_server.protocol,
|
.protocol = args->mount_server.protocol,
|
||||||
.fh = root_fh,
|
.fh = root_fh,
|
||||||
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
||||||
|
.auth_flav_len = &auth_flavor_len,
|
||||||
};
|
};
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -2249,6 +2290,11 @@ static void nfs4_fill_super(struct super_block *sb)
|
||||||
nfs_initialise_sb(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
|
* Validate NFSv4 mount options
|
||||||
*/
|
*/
|
||||||
|
@ -2346,6 +2392,8 @@ static int nfs4_validate_mount_data(void *options,
|
||||||
|
|
||||||
nfs_validate_transport_protocol(args);
|
nfs_validate_transport_protocol(args);
|
||||||
|
|
||||||
|
nfs4_validate_mount_flags(args);
|
||||||
|
|
||||||
if (args->auth_flavor_len > 1)
|
if (args->auth_flavor_len > 1)
|
||||||
goto out_inval_auth;
|
goto out_inval_auth;
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ extern struct svc_procedure nlmsvc_procedures4[];
|
||||||
extern int nlmsvc_grace_period;
|
extern int nlmsvc_grace_period;
|
||||||
extern unsigned long nlmsvc_timeout;
|
extern unsigned long nlmsvc_timeout;
|
||||||
extern int nsm_use_hostnames;
|
extern int nsm_use_hostnames;
|
||||||
extern int nsm_local_state;
|
extern u32 nsm_local_state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lockd client functions
|
* Lockd client functions
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
#define NFSMODE_SOCK 0140000
|
#define NFSMODE_SOCK 0140000
|
||||||
#define NFSMODE_FIFO 0010000
|
#define NFSMODE_FIFO 0010000
|
||||||
|
|
||||||
#define NFS_MNT_PROGRAM 100005
|
#define NFS_MNT_PROGRAM 100005
|
||||||
#define NFS_MNT_PORT 627
|
#define NFS_MNT_VERSION 1
|
||||||
|
#define NFS_MNT3_VERSION 3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NFS stats. The good thing with these values is that NFSv3 errors are
|
* 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_READDIR 16
|
||||||
#define NFSPROC_STATFS 17
|
#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 */
|
#endif /* _LINUX_NFS2_H */
|
||||||
|
|
|
@ -88,12 +88,7 @@ struct nfs3_fh {
|
||||||
#define NFS3PROC_PATHCONF 20
|
#define NFS3PROC_PATHCONF 20
|
||||||
#define NFS3PROC_COMMIT 21
|
#define NFS3PROC_COMMIT 21
|
||||||
|
|
||||||
#define NFS_MNT3_PROGRAM 100005
|
|
||||||
#define NFS_MNT3_VERSION 3
|
#define NFS_MNT3_VERSION 3
|
||||||
#define MOUNTPROC3_NULL 0
|
|
||||||
#define MOUNTPROC3_MNT 1
|
|
||||||
#define MOUNTPROC3_UMNT 3
|
|
||||||
#define MOUNTPROC3_UMNTALL 4
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__KERNEL__)
|
#if defined(__KERNEL__)
|
||||||
|
|
|
@ -1965,6 +1965,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
|
||||||
*/
|
*/
|
||||||
set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
|
set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
|
||||||
xprt_force_disconnect(xprt);
|
xprt_force_disconnect(xprt);
|
||||||
|
break;
|
||||||
case -ECONNREFUSED:
|
case -ECONNREFUSED:
|
||||||
case -ECONNRESET:
|
case -ECONNRESET:
|
||||||
case -ENETUNREACH:
|
case -ENETUNREACH:
|
||||||
|
|
Loading…
Reference in a new issue