Commit bd81ccea authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.7' of git://linux-nfs.org/~bfields/linux

Pull nfsd update from J Bruce Fields:
 "Another relatively quiet cycle.  There was some progress on my
  remaining 4.1 todo's, but a couple of them were just of the form
  "check that we do X correctly", so didn't have much affect on the
  code.

  Other than that, a bunch of cleanup and some bugfixes (including an
  annoying NFSv4.0 state leak and a busy-loop in the server that could
  cause it to peg the CPU without making progress)."

* 'for-3.7' of git://linux-nfs.org/~bfields/linux: (46 commits)
  UAPI: (Scripted) Disintegrate include/linux/sunrpc
  UAPI: (Scripted) Disintegrate include/linux/nfsd
  nfsd4: don't allow reclaims of expired clients
  nfsd4: remove redundant callback probe
  nfsd4: expire old client earlier
  nfsd4: separate session allocation and initialization
  nfsd4: clean up session allocation
  nfsd4: minor free_session cleanup
  nfsd4: new_conn_from_crses should only allocate
  nfsd4: separate connection allocation and initialization
  nfsd4: reject bad forechannel attrs earlier
  nfsd4: enforce per-client sessions/no-sessions distinction
  nfsd4: set cl_minorversion at create time
  nfsd4: don't pin clientids to pseudoflavors
  nfsd4: fix bind_conn_to_session xdr comment
  nfsd4: cast readlink() bug argument
  NFSD: pass null terminated buf to kstrtouint()
  nfsd: remove duplicate init in nfsd4_cb_recall
  nfsd4: eliminate redundant nfs4_free_stateid
  fs/nfsd/nfs4idmap.c: adjust inconsistent IS_ERR and PTR_ERR
  ...
parents 98260daa a9ca4043
Administrative interfaces for nfsd
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that normally these interfaces are used only by the utilities in
nfs-utils.
nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem,
which is normally mounted at /proc/fs/nfsd/.
The server is always started by the first write of a nonzero value to
nfsd/threads.
Before doing that, NFSD can be told which sockets to listen on by
writing to nfsd/portlist; that write may be:
- an ascii-encoded file descriptor, which should refer to a
bound (and listening, for tcp) socket, or
- "transportname port", where transportname is currently either
"udp", "tcp", or "rdma".
If nfsd is started without doing any of these, then it will create one
udp and one tcp listener at port 2049 (see nfsd_init_socks).
On startup, nfsd and lockd grace periods start.
nfsd is shut down by a write of 0 to nfsd/threads. All locks and state
are thrown away at that point.
Between startup and shutdown, the number of threads may be adjusted up
or down by additional writes to nfsd/threads or by writes to
nfsd/pool_threads.
For more detail about files under nfsd/ and what they control, see
fs/nfsd/nfsctl.c; most of them have detailed comments.
Implementation notes
^^^^^^^^^^^^^^^^^^^^
Note that the rpc server requires the caller to serialize addition and
removal of listening sockets, and startup and shutdown of the server.
For nfsd this is done using nfsd_mutex.
...@@ -126,7 +126,7 @@ static void restart_grace(void) ...@@ -126,7 +126,7 @@ static void restart_grace(void)
static int static int
lockd(void *vrqstp) lockd(void *vrqstp)
{ {
int err = 0, preverr = 0; int err = 0;
struct svc_rqst *rqstp = vrqstp; struct svc_rqst *rqstp = vrqstp;
/* try_to_freeze() is called from svc_recv() */ /* try_to_freeze() is called from svc_recv() */
...@@ -165,21 +165,8 @@ lockd(void *vrqstp) ...@@ -165,21 +165,8 @@ lockd(void *vrqstp)
* recvfrom routine. * recvfrom routine.
*/ */
err = svc_recv(rqstp, timeout); err = svc_recv(rqstp, timeout);
if (err == -EAGAIN || err == -EINTR) { if (err == -EAGAIN || err == -EINTR)
preverr = err;
continue; continue;
}
if (err < 0) {
if (err != preverr) {
printk(KERN_WARNING "%s: unexpected error "
"from svc_recv (%d)\n", __func__, err);
preverr = err;
}
schedule_timeout_interruptible(HZ);
continue;
}
preverr = err;
dprintk("lockd: request from %s\n", dprintk("lockd: request from %s\n",
svc_print_addr(rqstp, buf, sizeof(buf))); svc_print_addr(rqstp, buf, sizeof(buf)));
......
...@@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease); ...@@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease);
void lease_get_mtime(struct inode *inode, struct timespec *time) void lease_get_mtime(struct inode *inode, struct timespec *time)
{ {
struct file_lock *flock = inode->i_flock; struct file_lock *flock = inode->i_flock;
if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK)) if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK))
*time = current_fs_time(inode->i_sb); *time = current_fs_time(inode->i_sb);
else else
*time = inode->i_mtime; *time = inode->i_mtime;
...@@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, ...@@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
} else { } else {
seq_printf(f, "%s ", seq_printf(f, "%s ",
(lease_breaking(fl)) (lease_breaking(fl))
? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
: (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
} }
if (inode) { if (inode) {
#ifdef WE_CAN_BREAK_LSLK_NOW #ifdef WE_CAN_BREAK_LSLK_NOW
......
...@@ -72,7 +72,7 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) ...@@ -72,7 +72,7 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
static int static int
nfs4_callback_svc(void *vrqstp) nfs4_callback_svc(void *vrqstp)
{ {
int err, preverr = 0; int err;
struct svc_rqst *rqstp = vrqstp; struct svc_rqst *rqstp = vrqstp;
set_freezable(); set_freezable();
...@@ -82,20 +82,8 @@ nfs4_callback_svc(void *vrqstp) ...@@ -82,20 +82,8 @@ nfs4_callback_svc(void *vrqstp)
* Listen for a request on the socket * Listen for a request on the socket
*/ */
err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
if (err == -EAGAIN || err == -EINTR) { if (err == -EAGAIN || err == -EINTR)
preverr = err;
continue; continue;
}
if (err < 0) {
if (err != preverr) {
printk(KERN_WARNING "NFS: %s: unexpected error "
"from svc_recv (%d)\n", __func__, err);
preverr = err;
}
schedule_timeout_uninterruptible(HZ);
continue;
}
preverr = err;
svc_process(rqstp); svc_process(rqstp);
} }
return 0; return 0;
......
...@@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, ...@@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
* There must be an encoding function for void results so svc_process * There must be an encoding function for void results so svc_process
* will work properly. * will work properly.
*/ */
int static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
{ {
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
......
...@@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, ...@@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
/* Now create the file and set attributes */ /* Now create the file and set attributes */
nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
attr, newfhp, attr, newfhp,
argp->createmode, argp->verf, NULL, NULL); argp->createmode, (u32 *)argp->verf, NULL, NULL);
RETURN_STATUS(nfserr); RETURN_STATUS(nfserr);
} }
......
...@@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp) ...@@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
cb->cb_msg.rpc_cred = callback_cred; cb->cb_msg.rpc_cred = callback_cred;
cb->cb_ops = &nfsd4_cb_recall_ops; cb->cb_ops = &nfsd4_cb_recall_ops;
dp->dl_retries = 1;
INIT_LIST_HEAD(&cb->cb_per_client); INIT_LIST_HEAD(&cb->cb_per_client);
cb->cb_done = true; cb->cb_done = true;
......
...@@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net) ...@@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net)
goto destroy_idtoname_cache; goto destroy_idtoname_cache;
nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
if (IS_ERR(nn->nametoid_cache)) { if (IS_ERR(nn->nametoid_cache)) {
rv = PTR_ERR(nn->idtoname_cache); rv = PTR_ERR(nn->nametoid_cache);
goto unregister_idtoname_cache; goto unregister_idtoname_cache;
} }
rv = cache_register_net(nn->nametoid_cache, net); rv = cache_register_net(nn->nametoid_cache, net);
...@@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel ...@@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
/* Just to make sure it's null-terminated: */ /* Just to make sure it's null-terminated: */
memcpy(buf, name, namelen); memcpy(buf, name, namelen);
buf[namelen] = '\0'; buf[namelen] = '\0';
ret = kstrtouint(name, 10, id); ret = kstrtouint(buf, 10, id);
return ret == 0; return ret == 0;
} }
......
...@@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
break; break;
case NFS4_OPEN_CLAIM_PREVIOUS: case NFS4_OPEN_CLAIM_PREVIOUS:
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
status = nfs4_check_open_reclaim(&open->op_clientid); status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
if (status) if (status)
goto out; goto out;
case NFS4_OPEN_CLAIM_FH: case NFS4_OPEN_CLAIM_FH:
...@@ -1054,8 +1054,8 @@ struct nfsd4_operation { ...@@ -1054,8 +1054,8 @@ struct nfsd4_operation {
char *op_name; char *op_name;
/* Try to get response size before operation */ /* Try to get response size before operation */
nfsd4op_rsize op_rsize_bop; nfsd4op_rsize op_rsize_bop;
stateid_setter op_get_currentstateid; stateid_getter op_get_currentstateid;
stateid_getter op_set_currentstateid; stateid_setter op_set_currentstateid;
}; };
static struct nfsd4_operation nfsd4_ops[]; static struct nfsd4_operation nfsd4_ops[];
......
This diff is collapsed.
...@@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, ...@@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
WRITE32(bcts->dir); WRITE32(bcts->dir);
/* XXX: ? */ /* Sorry, we do not yet support RDMA over 4.1: */
WRITE32(0); WRITE32(0);
ADJUST_ARGS(); ADJUST_ARGS();
} }
......
...@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) ...@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
return rv; return rv;
if (newthreads < 0) if (newthreads < 0)
return -EINVAL; return -EINVAL;
rv = nfsd_svc(NFS_PORT, newthreads); rv = nfsd_svc(newthreads);
if (rv < 0) if (rv < 0)
return rv; return rv;
} else } else
...@@ -682,25 +682,6 @@ static ssize_t __write_ports_addfd(char *buf) ...@@ -682,25 +682,6 @@ static ssize_t __write_ports_addfd(char *buf)
return err; return err;
} }
/*
* A '-' followed by the 'name' of a socket means we close the socket.
*/
static ssize_t __write_ports_delfd(char *buf)
{
char *toclose;
int len = 0;
toclose = kstrdup(buf + 1, GFP_KERNEL);
if (toclose == NULL)
return -ENOMEM;
if (nfsd_serv != NULL)
len = svc_sock_names(nfsd_serv, buf,
SIMPLE_TRANSACTION_LIMIT, toclose);
kfree(toclose);
return len;
}
/* /*
* A transport listener is added by writing it's transport name and * A transport listener is added by writing it's transport name and
* a port number. * a port number.
...@@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf) ...@@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf)
int port, err; int port, err;
struct net *net = &init_net; struct net *net = &init_net;
if (sscanf(buf, "%15s %4u", transport, &port) != 2) if (sscanf(buf, "%15s %5u", transport, &port) != 2)
return -EINVAL; return -EINVAL;
if (port < 1 || port > USHRT_MAX) if (port < 1 || port > USHRT_MAX)
...@@ -746,31 +727,6 @@ static ssize_t __write_ports_addxprt(char *buf) ...@@ -746,31 +727,6 @@ static ssize_t __write_ports_addxprt(char *buf)
return err; return err;
} }
/*
* A transport listener is removed by writing a "-", it's transport
* name, and it's port number.
*/
static ssize_t __write_ports_delxprt(char *buf)
{
struct svc_xprt *xprt;
char transport[16];
int port;
if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
return -EINVAL;
if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
return -EINVAL;
xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
if (xprt == NULL)
return -ENOTCONN;
svc_close_xprt(xprt);
svc_xprt_put(xprt);
return 0;
}
static ssize_t __write_ports(struct file *file, char *buf, size_t size) static ssize_t __write_ports(struct file *file, char *buf, size_t size)
{ {
if (size == 0) if (size == 0)
...@@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) ...@@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
if (isdigit(buf[0])) if (isdigit(buf[0]))
return __write_ports_addfd(buf); return __write_ports_addfd(buf);
if (buf[0] == '-' && isdigit(buf[1]))
return __write_ports_delfd(buf);
if (isalpha(buf[0])) if (isalpha(buf[0]))
return __write_ports_addxprt(buf); return __write_ports_addxprt(buf);
if (buf[0] == '-' && isalpha(buf[1]))
return __write_ports_delxprt(buf);
return -EINVAL; return -EINVAL;
} }
...@@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) ...@@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
* OR * OR
* *
* Input: * Input:
* buf: C string containing a "-" followed
* by an integer value representing a
* previously passed in socket file
* descriptor
* size: non-zero length of C string in @buf
* Output:
* On success: NFS service no longer listens on that socket;
* passed-in buffer filled with a '\n'-terminated C
* string containing a unique name of the listener;
* return code is the size in bytes of the string
* On error: return code is a negative errno value
*
* OR
*
* Input:
* buf: C string containing a transport * buf: C string containing a transport
* name and an unsigned integer value * name and an unsigned integer value
* representing the port to listen on, * representing the port to listen on,
...@@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) ...@@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
* Output: * Output:
* On success: returns zero; NFS service is started * On success: returns zero; NFS service is started
* On error: return code is a negative errno value * On error: return code is a negative errno value
*
* OR
*
* Input:
* buf: C string containing a "-" followed
* by a transport name and an unsigned
* integer value representing the port
* to listen on, separated by whitespace
* size: non-zero length of C string in @buf
* Output:
* On success: returns zero; NFS service no longer listens
* on that transport
* On error: return code is a negative errno value
*/ */
static ssize_t write_ports(struct file *file, char *buf, size_t size) static ssize_t write_ports(struct file *file, char *buf, size_t size)
{ {
...@@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size) ...@@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
return nfsd4_write_time(file, buf, size, &nfsd4_grace); return nfsd4_write_time(file, buf, size, &nfsd4_grace);
} }
extern char *nfs4_recoverydir(void);
static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
{ {
char *mesg = buf; char *mesg = buf;
......
...@@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op; ...@@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op;
/* /*
* Function prototypes. * Function prototypes.
*/ */
int nfsd_svc(unsigned short port, int nrservs); int nfsd_svc(int nrservs);
int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
int nfsd_nrthreads(void); int nfsd_nrthreads(void);
...@@ -124,6 +124,7 @@ int nfs4_state_start(void); ...@@ -124,6 +124,7 @@ int nfs4_state_start(void);
void nfs4_state_shutdown(void); void nfs4_state_shutdown(void);
void nfs4_reset_lease(time_t leasetime); void nfs4_reset_lease(time_t leasetime);
int nfs4_reset_recoverydir(char *recdir); int nfs4_reset_recoverydir(char *recdir);
char * nfs4_recoverydir(void);
#else #else
static inline void nfs4_state_init(void) { } static inline void nfs4_state_init(void) { }
static inline int nfsd4_init_slabs(void) { return 0; } static inline int nfsd4_init_slabs(void) { return 0; }
...@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; } ...@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; }
static inline void nfs4_state_shutdown(void) { } static inline void nfs4_state_shutdown(void) { }
static inline void nfs4_reset_lease(time_t leasetime) { } static inline void nfs4_reset_lease(time_t leasetime) { }
static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
static inline char * nfs4_recoverydir(void) {return NULL; }
#endif #endif
/* /*
......
...@@ -183,18 +183,18 @@ int nfsd_nrthreads(void) ...@@ -183,18 +183,18 @@ int nfsd_nrthreads(void)
return rv; return rv;
} }
static int nfsd_init_socks(int port) static int nfsd_init_socks(void)
{ {
int error; int error;
if (!list_empty(&nfsd_serv->sv_permsocks)) if (!list_empty(&nfsd_serv->sv_permsocks))
return 0; return 0;
error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT,
SVC_SOCK_DEFAULTS); SVC_SOCK_DEFAULTS);
if (error < 0) if (error < 0)
return error; return error;
error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT,
SVC_SOCK_DEFAULTS); SVC_SOCK_DEFAULTS);
if (error < 0) if (error < 0)
return error; return error;
...@@ -204,7 +204,7 @@ static int nfsd_init_socks(int port) ...@@ -204,7 +204,7 @@ static int nfsd_init_socks(int port)
static bool nfsd_up = false; static bool nfsd_up = false;
static int nfsd_startup(unsigned short port, int nrservs) static int nfsd_startup(int nrservs)
{ {
int ret; int ret;
...@@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs) ...@@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
ret = nfsd_racache_init(2*nrservs); ret = nfsd_racache_init(2*nrservs);
if (ret) if (ret)
return ret; return ret;
ret = nfsd_init_socks(port); ret = nfsd_init_socks();
if (ret) if (ret)
goto out_racache; goto out_racache;
ret = lockd_up(&init_net); ret = lockd_up(&init_net);
...@@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) ...@@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
* this is the first time nrservs is nonzero. * this is the first time nrservs is nonzero.
*/ */
int int
nfsd_svc(unsigned short port, int nrservs) nfsd_svc(int nrservs)
{ {
int error; int error;
bool nfsd_up_before; bool nfsd_up_before;
...@@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs) ...@@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs)
nfsd_up_before = nfsd_up; nfsd_up_before = nfsd_up;
error = nfsd_startup(port, nrservs); error = nfsd_startup(nrservs);
if (error) if (error)
goto out_destroy; goto out_destroy;
error = svc_set_num_threads(nfsd_serv, NULL, nrservs); error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
...@@ -487,7 +487,7 @@ static int ...@@ -487,7 +487,7 @@ static int
nfsd(void *vrqstp) nfsd(void *vrqstp)
{ {
struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
int err, preverr = 0; int err;
/* Lock module and set up kernel thread */ /* Lock module and set up kernel thread */
mutex_lock(&nfsd_mutex); mutex_lock(&nfsd_mutex);
...@@ -534,16 +534,6 @@ nfsd(void *vrqstp) ...@@ -534,16 +534,6 @@ nfsd(void *vrqstp)
; ;
if (err == -EINTR) if (err == -EINTR)
break; break;
else if (err < 0) {
if (err != preverr) {
printk(KERN_WARNING "%s: unexpected error "
"from svc_recv (%d)\n", __func__, -err);
preverr = err;
}
schedule_timeout_uninterruptible(HZ);
continue;
}
validate_process_creds(); validate_process_creds();
svc_process(rqstp); svc_process(rqstp);
validate_process_creds(); validate_process_creds();
......
...@@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so) ...@@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
return container_of(so, struct nfs4_lockowner, lo_owner); return container_of(so, struct nfs4_lockowner, lo_owner);
} }
/* /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
* nfs4_file: a file opened by some number of (open) nfs4_stateowners.
* o fi_perfile list is used to search for conflicting
* share_acces, share_deny on the file.
*/
struct nfs4_file { struct nfs4_file {
atomic_t fi_ref; atomic_t fi_ref;
struct list_head fi_hash; /* hash by "struct inode *" */ struct list_head fi_hash; /* hash by "struct inode *" */
...@@ -459,7 +455,7 @@ extern void nfs4_unlock_state(void); ...@@ -459,7 +455,7 @@ extern void nfs4_unlock_state(void);
extern int nfs4_in_grace(void); extern int nfs4_in_grace(void);
extern void nfs4_release_reclaim(void); extern void nfs4_release_reclaim(void);
extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
extern __be32 nfs4_check_open_reclaim(clientid_t *clid); extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_openowner(struct nfs4_openowner *);
extern void nfs4_free_lockowner(struct nfs4_lockowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *);
extern int set_callback_cred(void); extern int set_callback_cred(void);
......
...@@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) ...@@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
*/ */
oldfs = get_fs(); set_fs(KERNEL_DS); oldfs = get_fs(); set_fs(KERNEL_DS);
host_err = inode->i_op->readlink(path.dentry, buf, *lenp); host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp);
set_fs(oldfs); set_fs(oldfs);
if (host_err < 0) if (host_err < 0)
......
header-y += cld.h
header-y += debug.h
header-y += export.h
header-y += nfsfh.h
header-y += stats.h
...@@ -5,44 +5,15 @@ ...@@ -5,44 +5,15 @@
* *
* Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
*/ */
#ifndef LINUX_NFSD_DEBUG_H #ifndef LINUX_NFSD_DEBUG_H
#define LINUX_NFSD_DEBUG_H #define LINUX_NFSD_DEBUG_H
#include <linux/sunrpc/debug.h> #include <uapi/linux/nfsd/debug.h>
/*
* Enable debugging for nfsd.
* Requires RPC_DEBUG.
*/
#ifdef RPC_DEBUG
# define NFSD_DEBUG 1
#endif
/*
* knfsd debug flags
*/
#define NFSDDBG_SOCK 0x0001
#define NFSDDBG_FH 0x0002
#define NFSDDBG_EXPORT 0x0004
#define NFSDDBG_SVC 0x0008
#define NFSDDBG_PROC 0x0010
#define NFSDDBG_FILEOP 0x0020
#define NFSDDBG_AUTH 0x0040
#define NFSDDBG_REPCACHE 0x0080
#define NFSDDBG_XDR 0x0100
#define NFSDDBG_LOCKD 0x0200
#define NFSDDBG_ALL 0x7FFF
#define NFSDDBG_NOCHANGE 0xFFFF
#ifdef __KERNEL__
# undef ifdebug # undef ifdebug
# ifdef NFSD_DEBUG # ifdef NFSD_DEBUG
# define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) # define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag)
# else # else
# define ifdebug(flag) if (0) # define ifdebug(flag) if (0)
# endif # endif
#endif /* __KERNEL__ */
#endif /* LINUX_NFSD_DEBUG_H */ #endif /* LINUX_NFSD_DEBUG_H */
...@@ -6,58 +6,11 @@ ...@@ -6,58 +6,11 @@
* *
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
*/ */
#ifndef NFSD_EXPORT_H #ifndef NFSD_EXPORT_H
#define NFSD_EXPORT_H #define NFSD_EXPORT_H
# include <linux/types.h>
#ifdef __KERNEL__
# include <linux/nfsd/nfsfh.h> # include <linux/nfsd/nfsfh.h>
#endif #include <uapi/linux/nfsd/export.h>
/*
* Important limits for the exports stuff.
*/
#define NFSCLNT_IDMAX 1024
#define NFSCLNT_ADDRMAX 16
#define NFSCLNT_KEYMAX 32
/*
* Export flags.
*/
#define NFSEXP_READONLY 0x0001
#define NFSEXP_INSECURE_PORT 0x0002
#define NFSEXP_ROOTSQUASH 0x0004
#define NFSEXP_ALLSQUASH 0x0008
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
/* 40 80 100 currently unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */
#define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
/*
* The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
* clients, and only to the single directory that is the root of the
* export; further lookup and readdir operations are treated as if every
* subdirectory was a mountpoint, and ignored if they are not themselves
* exported. This is used by nfsd and mountd to construct the NFSv4
* pseudofilesystem, which provides access only to paths leading to each
* exported filesystem.
*/
#define NFSEXP_V4ROOT 0x10000
/* All flags that we claim to support. (Note we don't support NOACL.) */
#define NFSEXP_ALLFLAGS 0x17E3F
/* The flags that may vary depending on security flavor: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
| NFSEXP_ALLSQUASH \
| NFSEXP_INSECURE_PORT)
#ifdef __KERNEL__
/* /*
* FS Locations * FS Locations
...@@ -154,7 +107,4 @@ static inline void exp_get(struct svc_export *exp) ...@@ -154,7 +107,4 @@ static inline void exp_get(struct svc_export *exp)
} }
struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *); struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
#endif /* __KERNEL__ */
#endif /* NFSD_EXPORT_H */ #endif /* NFSD_EXPORT_H */
...@@ -10,117 +10,11 @@ ...@@ -10,117 +10,11 @@
* *
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/ */
#ifndef _LINUX_NFSD_FH_H #ifndef _LINUX_NFSD_FH_H
#define _LINUX_NFSD_FH_H #define _LINUX_NFSD_FH_H
#include <linux/types.h>
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs3.h>
#include <linux/nfs4.h>
#ifdef __KERNEL__
# include <linux/sunrpc/svc.h> # include <linux/sunrpc/svc.h>
#endif #include <uapi/linux/nfsd/nfsfh.h>
/*
* This is the old "dentry style" Linux NFSv2 file handle.
*
* The xino and xdev fields are currently used to transport the
* ino/dev of the exported inode.
*/
struct nfs_fhbase_old {
__u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
__u32 fb_ino; /* our inode number */
__u32 fb_dirino; /* dir inode number, 0 for directories */
__u32 fb_dev; /* our device */
__u32 fb_xdev;
__u32 fb_xino;
__u32 fb_generation;
};
/*
* This is the new flexible, extensible style NFSv2/v3 file handle.
* by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
*
* The file handle starts with a sequence of four-byte words.
* The first word contains a version number (1) and three descriptor bytes
* that tell how the remaining 3 variable length fields should be handled.
* These three bytes are auth_type, fsid_type and fileid_type.
*
* All four-byte values are in host-byte-order.
*
* The auth_type field specifies how the filehandle can be authenticated
* This might allow a file to be confirmed to be in a writable part of a
* filetree without checking the path from it up to the root.
* Current values:
* 0 - No authentication. fb_auth is 0 bytes long
* Possible future values:
* 1 - 4 bytes taken from MD5 hash of the remainer of the file handle
* prefixed by a secret and with the important export flags.
*
* The fsid_type identifies how the filesystem (or export point) is
* encoded.
* Current values:
* 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
* NOTE: we cannot use the kdev_t device id value, because kdev_t.h
* says we mustn't. We must break it up and reassemble.
* 1 - 4 byte user specified identifier
* 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
* 3 - 4 byte device id, encoded for user-space, 4 byte inode number
* 4 - 4 byte inode number and 4 byte uuid
* 5 - 8 byte uuid
* 6 - 16 byte uuid
* 7 - 8 byte inode number and 16 byte uuid
*
* The fileid_type identified how the file within the filesystem is encoded.
* This is (will be) passed to, and set by, the underlying filesystem if it supports
* filehandle operations. The filesystem must not use the value '0' or '0xff' and may
* only use the values 1 and 2 as defined below:
* Current values:
* 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes.
* 1 - 32bit inode number, 32 bit generation number.
* 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
*
*/
struct nfs_fhbase_new {
__u8 fb_version; /* == 1, even => nfs_fhbase_old */
__u8 fb_auth_type;
__u8 fb_fsid_type;
__u8 fb_fileid_type;
__u32 fb_auth[1];
/* __u32 fb_fsid[0]; floating */
/* __u32 fb_fileid[0]; floating */
};
struct knfsd_fh {
unsigned int fh_size; /* significant for NFSv3.
* Points to the current size while building
* a new file handle
*/
union {
struct nfs_fhbase_old fh_old;
__u32 fh_pad[NFS4_FHSIZE/4];
struct nfs_fhbase_new fh_new;
} fh_base;
};
#define ofh_dcookie fh_base.fh_old.fb_dcookie
#define ofh_ino fh_base.fh_old.fb_ino
#define ofh_dirino fh_base.fh_old.fb_dirino
#define ofh_dev fh_base.fh_old.fb_dev
#define ofh_xdev fh_base.fh_old.fb_xdev
#define ofh_xino fh_base.fh_old.fb_xino
#define ofh_generation fh_base.fh_old.fb_generation
#define fh_version fh_base.fh_new.fb_version
#define fh_fsid_type fh_base.fh_new.fb_fsid_type
#define fh_auth_type fh_base.fh_new.fb_auth_type
#define fh_fileid_type fh_base.fh_new.fb_fileid_type
#define fh_auth fh_base.fh_new.fb_auth
#define fh_fsid fh_base.fh_new.fb_auth
#ifdef __KERNEL__
static inline __u32 ino_t_to_u32(ino_t ino) static inline __u32 ino_t_to_u32(ino_t ino)
{ {
...@@ -166,7 +60,4 @@ typedef struct svc_fh { ...@@ -166,7 +60,4 @@ typedef struct svc_fh {
} svc_fh; } svc_fh;
#endif /* __KERNEL__ */
#endif /* _LINUX_NFSD_FH_H */ #endif /* _LINUX_NFSD_FH_H */
...@@ -5,16 +5,11 @@ ...@@ -5,16 +5,11 @@
* *
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/ */
#ifndef LINUX_NFSD_STATS_H #ifndef LINUX_NFSD_STATS_H
#define LINUX_NFSD_STATS_H #define LINUX_NFSD_STATS_H
#include <linux/nfs4.h> #include <uapi/linux/nfsd/stats.h>
/* thread usage wraps very million seconds (approx one fortnight) */
#define NFSD_USAGE_WRAP (HZ*1000000)
#ifdef __KERNEL__
struct nfsd_stats { struct nfsd_stats {
unsigned int rchits; /* repcache hits */ unsigned int rchits; /* repcache hits */
...@@ -47,5 +42,4 @@ extern struct svc_stat nfsd_svcstats; ...@@ -47,5 +42,4 @@ extern struct svc_stat nfsd_svcstats;
void nfsd_stat_init(void); void nfsd_stat_init(void);
void nfsd_stat_shutdown(void); void nfsd_stat_shutdown(void);
#endif /* __KERNEL__ */
#endif /* LINUX_NFSD_STATS_H */ #endif /* LINUX_NFSD_STATS_H */
...@@ -5,28 +5,11 @@ ...@@ -5,28 +5,11 @@
* *
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/ */
#ifndef _LINUX_SUNRPC_DEBUG_H_ #ifndef _LINUX_SUNRPC_DEBUG_H_
#define _LINUX_SUNRPC_DEBUG_H_ #define _LINUX_SUNRPC_DEBUG_H_
/* #include <uapi/linux/sunrpc/debug.h>
* RPC debug facilities
*/
#define RPCDBG_XPRT 0x0001
#define RPCDBG_CALL 0x0002
#define RPCDBG_DEBUG 0x0004
#define RPCDBG_NFS 0x0008
#define RPCDBG_AUTH 0x0010
#define RPCDBG_BIND 0x0020
#define RPCDBG_SCHED 0x0040
#define RPCDBG_TRANS 0x0080
#define RPCDBG_SVCXPRT 0x0100
#define RPCDBG_SVCDSP 0x0200
#define RPCDBG_MISC 0x0400
#define RPCDBG_CACHE 0x0800
#define RPCDBG_ALL 0x7fff
#ifdef __KERNEL__
/* /*
* Enable RPC debugging/profiling. * Enable RPC debugging/profiling.
...@@ -87,24 +70,4 @@ void rpc_register_sysctl(void); ...@@ -87,24 +70,4 @@ void rpc_register_sysctl(void);
void rpc_unregister_sysctl(void); void rpc_unregister_sysctl(void);
#endif #endif
#endif /* __KERNEL__ */
/*
* Declarations for the sysctl debug interface, which allows to read or
* change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
* module currently registers its sysctl table dynamically, the sysctl path
* for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
*/
enum {
CTL_RPCDEBUG = 1,
CTL_NFSDEBUG,
CTL_NFSDDEBUG,
CTL_NLMDEBUG,
CTL_SLOTTABLE_UDP,
CTL_SLOTTABLE_TCP,
CTL_MIN_RESVPORT,
CTL_MAX_RESVPORT,
};
#endif /* _LINUX_SUNRPC_DEBUG_H_ */ #endif /* _LINUX_SUNRPC_DEBUG_H_ */
...@@ -114,7 +114,6 @@ void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *, ...@@ -114,7 +114,6 @@ void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
int svc_create_xprt(struct svc_serv *, const char *, struct net *, int svc_create_xprt(struct svc_serv *, const char *, struct net *,
const int, const unsigned short, int); const int, const unsigned short, int);
void svc_xprt_enqueue(struct svc_xprt *xprt); void svc_xprt_enqueue(struct svc_xprt *xprt);
void svc_xprt_received(struct svc_xprt *);
void svc_xprt_put(struct svc_xprt *xprt); void svc_xprt_put(struct svc_xprt *xprt);
void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);
void svc_close_xprt(struct svc_xprt *xprt); void svc_close_xprt(struct svc_xprt *xprt);
...@@ -124,6 +123,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, ...@@ -124,6 +123,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
struct net *net, const sa_family_t af, struct net *net, const sa_family_t af,
const unsigned short port); const unsigned short port);
int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt);
static inline void svc_xprt_get(struct svc_xprt *xprt) static inline void svc_xprt_get(struct svc_xprt *xprt)
{ {
...@@ -166,8 +166,7 @@ static inline size_t svc_addr_len(const struct sockaddr *sa) ...@@ -166,8 +166,7 @@ static inline size_t svc_addr_len(const struct sockaddr *sa)
case AF_INET6: case AF_INET6:
return sizeof(struct sockaddr_in6); return sizeof(struct sockaddr_in6);
} }
BUG();
return 0;
} }
static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt) static inline unsigned short svc_xprt_local_port(const struct svc_xprt *xprt)
......
...@@ -39,9 +39,6 @@ int svc_recv(struct svc_rqst *, long); ...@@ -39,9 +39,6 @@ int svc_recv(struct svc_rqst *, long);
int svc_send(struct svc_rqst *); int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *); void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv); void svc_sock_update_bufs(struct svc_serv *serv);
int svc_sock_names(struct svc_serv *serv, char *buf,
const size_t buflen,
const char *toclose);
int svc_addsock(struct svc_serv *serv, const int fd, int svc_addsock(struct svc_serv *serv, const int fd,
char *name_return, const size_t len); char *name_return, const size_t len);
void svc_init_xprt_sock(void); void svc_init_xprt_sock(void);
......
# UAPI Header export list # UAPI Header export list
header-y += cld.h
header-y += debug.h
header-y += export.h
header-y += nfsfh.h
header-y += stats.h
/*
* linux/include/linux/nfsd/debug.h
*
* Debugging-related stuff for nfsd
*
* Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef _UAPILINUX_NFSD_DEBUG_H
#define _UAPILINUX_NFSD_DEBUG_H
#include <linux/sunrpc/debug.h>
/*
* Enable debugging for nfsd.
* Requires RPC_DEBUG.
*/
#ifdef RPC_DEBUG
# define NFSD_DEBUG 1
#endif
/*
* knfsd debug flags
*/
#define NFSDDBG_SOCK 0x0001
#define NFSDDBG_FH 0x0002
#define NFSDDBG_EXPORT 0x0004
#define NFSDDBG_SVC 0x0008
#define NFSDDBG_PROC 0x0010
#define NFSDDBG_FILEOP 0x0020
#define NFSDDBG_AUTH 0x0040
#define NFSDDBG_REPCACHE 0x0080
#define NFSDDBG_XDR 0x0100
#define NFSDDBG_LOCKD 0x0200
#define NFSDDBG_ALL 0x7FFF
#define NFSDDBG_NOCHANGE 0xFFFF
#endif /* _UAPILINUX_NFSD_DEBUG_H */
/*
* include/linux/nfsd/export.h
*
* Public declarations for NFS exports. The definitions for the
* syscall interface are in nfsctl.h
*
* Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef _UAPINFSD_EXPORT_H
#define _UAPINFSD_EXPORT_H
# include <linux/types.h>
/*
* Important limits for the exports stuff.
*/
#define NFSCLNT_IDMAX 1024
#define NFSCLNT_ADDRMAX 16
#define NFSCLNT_KEYMAX 32
/*
* Export flags.
*/
#define NFSEXP_READONLY 0x0001
#define NFSEXP_INSECURE_PORT 0x0002
#define NFSEXP_ROOTSQUASH 0x0004
#define NFSEXP_ALLSQUASH 0x0008
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
/* 40 80 100 currently unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect; no longer supported */
#define NFSEXP_FSID 0x2000
#define NFSEXP_CROSSMOUNT 0x4000
#define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
/*
* The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
* clients, and only to the single directory that is the root of the
* export; further lookup and readdir operations are treated as if every
* subdirectory was a mountpoint, and ignored if they are not themselves
* exported. This is used by nfsd and mountd to construct the NFSv4
* pseudofilesystem, which provides access only to paths leading to each
* exported filesystem.
*/
#define NFSEXP_V4ROOT 0x10000
/* All flags that we claim to support. (Note we don't support NOACL.) */
#define NFSEXP_ALLFLAGS 0x17E3F
/* The flags that may vary depending on security flavor: */
#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
| NFSEXP_ALLSQUASH \
| NFSEXP_INSECURE_PORT)
#endif /* _UAPINFSD_EXPORT_H */
/*
* include/linux/nfsd/nfsfh.h
*
* This file describes the layout of the file handles as passed
* over the wire.
*
* Earlier versions of knfsd used to sign file handles using keyed MD5
* or SHA. I've removed this code, because it doesn't give you more
* security than blocking external access to port 2049 on your firewall.
*
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef _UAPI_LINUX_NFSD_FH_H
#define _UAPI_LINUX_NFSD_FH_H
#include <linux/types.h>
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs3.h>
#include <linux/nfs4.h>
/*
* This is the old "dentry style" Linux NFSv2 file handle.
*
* The xino and xdev fields are currently used to transport the
* ino/dev of the exported inode.
*/
struct nfs_fhbase_old {
__u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
__u32 fb_ino; /* our inode number */
__u32 fb_dirino; /* dir inode number, 0 for directories */
__u32 fb_dev; /* our device */
__u32 fb_xdev;
__u32 fb_xino;
__u32 fb_generation;
};
/*
* This is the new flexible, extensible style NFSv2/v3 file handle.
* by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
*
* The file handle starts with a sequence of four-byte words.
* The first word contains a version number (1) and three descriptor bytes
* that tell how the remaining 3 variable length fields should be handled.
* These three bytes are auth_type, fsid_type and fileid_type.
*
* All four-byte values are in host-byte-order.
*
* The auth_type field specifies how the filehandle can be authenticated
* This might allow a file to be confirmed to be in a writable part of a
* filetree without checking the path from it up to the root.
* Current values:
* 0 - No authentication. fb_auth is 0 bytes long
* Possible future values:
* 1 - 4 bytes taken from MD5 hash of the remainer of the file handle
* prefixed by a secret and with the important export flags.
*
* The fsid_type identifies how the filesystem (or export point) is
* encoded.
* Current values:
* 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
* NOTE: we cannot use the kdev_t device id value, because kdev_t.h
* says we mustn't. We must break it up and reassemble.
* 1 - 4 byte user specified identifier
* 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
* 3 - 4 byte device id, encoded for user-space, 4 byte inode number
* 4 - 4 byte inode number and 4 byte uuid
* 5 - 8 byte uuid
* 6 - 16 byte uuid
* 7 - 8 byte inode number and 16 byte uuid
*
* The fileid_type identified how the file within the filesystem is encoded.
* This is (will be) passed to, and set by, the underlying filesystem if it supports
* filehandle operations. The filesystem must not use the value '0' or '0xff' and may
* only use the values 1 and 2 as defined below:
* Current values:
* 0 - The root, or export point, of the filesystem. fb_fileid is 0 bytes.
* 1 - 32bit inode number, 32 bit generation number.
* 2 - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
*
*/
struct nfs_fhbase_new {
__u8 fb_version; /* == 1, even => nfs_fhbase_old */
__u8 fb_auth_type;
__u8 fb_fsid_type;
__u8 fb_fileid_type;
__u32 fb_auth[1];
/* __u32 fb_fsid[0]; floating */
/* __u32 fb_fileid[0]; floating */
};
struct knfsd_fh {
unsigned int fh_size; /* significant for NFSv3.
* Points to the current size while building
* a new file handle
*/
union {
struct nfs_fhbase_old fh_old;
__u32 fh_pad[NFS4_FHSIZE/4];
struct nfs_fhbase_new fh_new;
} fh_base;
};
#define ofh_dcookie fh_base.fh_old.fb_dcookie
#define ofh_ino fh_base.fh_old.fb_ino
#define ofh_dirino fh_base.fh_old.fb_dirino
#define ofh_dev fh_base.fh_old.fb_dev
#define ofh_xdev fh_base.fh_old.fb_xdev
#define ofh_xino fh_base.fh_old.fb_xino
#define ofh_generation fh_base.fh_old.fb_generation
#define fh_version fh_base.fh_new.fb_version
#define fh_fsid_type fh_base.fh_new.fb_fsid_type
#define fh_auth_type fh_base.fh_new.fb_auth_type
#define fh_fileid_type fh_base.fh_new.fb_fileid_type
#define fh_auth fh_base.fh_new.fb_auth
#define fh_fsid fh_base.fh_new.fb_auth
#endif /* _UAPI_LINUX_NFSD_FH_H */
/*
* linux/include/linux/nfsd/stats.h
*
* Statistics for NFS server.
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef _UAPILINUX_NFSD_STATS_H
#define _UAPILINUX_NFSD_STATS_H
#include <linux/nfs4.h>
/* thread usage wraps very million seconds (approx one fortnight) */
#define NFSD_USAGE_WRAP (HZ*1000000)
#endif /* _UAPILINUX_NFSD_STATS_H */
# UAPI Header export list # UAPI Header export list
header-y += debug.h
/*
* linux/include/linux/sunrpc/debug.h
*
* Debugging support for sunrpc module
*
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#ifndef _UAPI_LINUX_SUNRPC_DEBUG_H_
#define _UAPI_LINUX_SUNRPC_DEBUG_H_
/*
* RPC debug facilities
*/
#define RPCDBG_XPRT 0x0001
#define RPCDBG_CALL 0x0002
#define RPCDBG_DEBUG 0x0004
#define RPCDBG_NFS 0x0008
#define RPCDBG_AUTH 0x0010
#define RPCDBG_BIND 0x0020
#define RPCDBG_SCHED 0x0040
#define RPCDBG_TRANS 0x0080
#define RPCDBG_SVCXPRT 0x0100
#define RPCDBG_SVCDSP 0x0200
#define RPCDBG_MISC 0x0400
#define RPCDBG_CACHE 0x0800
#define RPCDBG_ALL 0x7fff
/*
* Declarations for the sysctl debug interface, which allows to read or
* change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
* module currently registers its sysctl table dynamically, the sysctl path
* for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
*/
enum {
CTL_RPCDEBUG = 1,
CTL_NFSDEBUG,
CTL_NFSDDEBUG,
CTL_NLMDEBUG,
CTL_SLOTTABLE_UDP,
CTL_SLOTTABLE_TCP,
CTL_MIN_RESVPORT,
CTL_MAX_RESVPORT,
};
#endif /* _UAPI_LINUX_SUNRPC_DEBUG_H_ */
This diff is collapsed.
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
int *errp, int flags); int flags);
static void svc_udp_data_ready(struct sock *, int); static void svc_udp_data_ready(struct sock *, int);
static int svc_udp_recvfrom(struct svc_rqst *); static int svc_udp_recvfrom(struct svc_rqst *);
static int svc_udp_sendto(struct svc_rqst *); static int svc_udp_sendto(struct svc_rqst *);
...@@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) ...@@ -305,57 +305,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
return len; return len;
} }
/**
* svc_sock_names - construct a list of listener names in a string
* @serv: pointer to RPC service
* @buf: pointer to a buffer to fill in with socket names
* @buflen: size of the buffer to be filled
* @toclose: pointer to '\0'-terminated C string containing the name
* of a listener to be closed
*
* Fills in @buf with a '\n'-separated list of names of listener
* sockets. If @toclose is not NULL, the socket named by @toclose
* is closed, and is not included in the output list.
*
* Returns positive length of the socket name string, or a negative
* errno value on error.
*/
int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
const char *toclose)
{
struct svc_sock *svsk, *closesk = NULL;
int len = 0;
if (!serv)
return 0;
spin_lock_bh(&serv->sv_lock);
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
if (onelen < 0) {
len = onelen;
break;
}
if (toclose && strcmp(toclose, buf + len) == 0) {
closesk = svsk;
svc_xprt_get(&closesk->sk_xprt);
} else
len += onelen;
}
spin_unlock_bh(&serv->sv_lock);
if (closesk) {
/* Should unregister with portmap, but you cannot
* unregister just one protocol...
*/
svc_close_xprt(&closesk->sk_xprt);
svc_xprt_put(&closesk->sk_xprt);
} else if (toclose)
return -ENOENT;
return len;
}
EXPORT_SYMBOL_GPL(svc_sock_names);
/* /*
* Check input queue length * Check input queue length
*/ */
...@@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) ...@@ -598,11 +547,9 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
dprintk("svc: recvfrom returned error %d\n", -err); dprintk("svc: recvfrom returned error %d\n", -err);
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
} }
return -EAGAIN; return 0;
} }
len = svc_addr_len(svc_addr(rqstp)); len = svc_addr_len(svc_addr(rqstp));
if (len == 0)
return -EAFNOSUPPORT;
rqstp->rq_addrlen = len; rqstp->rq_addrlen = len;
if (skb->tstamp.tv64 == 0) { if (skb->tstamp.tv64 == 0) {
skb->tstamp = ktime_get_real(); skb->tstamp = ktime_get_real();
...@@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) ...@@ -620,10 +567,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
if (!svc_udp_get_dest_address(rqstp, cmh)) { if (!svc_udp_get_dest_address(rqstp, cmh)) {
net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n",
cmh->cmsg_level, cmh->cmsg_type); cmh->cmsg_level, cmh->cmsg_type);
out_free: goto out_free;
trace_kfree_skb(skb, svc_udp_recvfrom);
skb_free_datagram_locked(svsk->sk_sk, skb);
return 0;
} }
rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp));
...@@ -662,6 +606,10 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) ...@@ -662,6 +606,10 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
serv->sv_stats->netudpcnt++; serv->sv_stats->netudpcnt++;
return len; return len;
out_free:
trace_kfree_skb(skb, svc_udp_recvfrom);
skb_free_datagram_locked(svsk->sk_sk, skb);
return 0;
} }
static int static int
...@@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) ...@@ -900,8 +848,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
*/ */
newsock->sk->sk_sndtimeo = HZ*30; newsock->sk->sk_sndtimeo = HZ*30;
if (!(newsvsk = svc_setup_socket(serv, newsock, &err, newsvsk = svc_setup_socket(serv, newsock,
(SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));
if (IS_ERR(newsvsk))
goto failed; goto failed;
svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen);
err = kernel_getsockname(newsock, sin, &slen); err = kernel_getsockname(newsock, sin, &slen);
...@@ -1174,13 +1123,13 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) ...@@ -1174,13 +1123,13 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
if (len != -EAGAIN) if (len != -EAGAIN)
goto err_other; goto err_other;
dprintk("RPC: TCP recvfrom got EAGAIN\n"); dprintk("RPC: TCP recvfrom got EAGAIN\n");
return -EAGAIN; return 0;
err_other: err_other:
printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
svsk->sk_xprt.xpt_server->sv_name, -len); svsk->sk_xprt.xpt_server->sv_name, -len);
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
err_noclose: err_noclose:
return -EAGAIN; /* record not complete */ return 0; /* record not complete */
} }
/* /*
...@@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs); ...@@ -1383,29 +1332,29 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
*/ */
static struct svc_sock *svc_setup_socket(struct svc_serv *serv, static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
struct socket *sock, struct socket *sock,
int *errp, int flags) int flags)
{ {
struct svc_sock *svsk; struct svc_sock *svsk;
struct sock *inet; struct sock *inet;
int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); int pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
int err = 0;
dprintk("svc: svc_setup_socket %p\n", sock); dprintk("svc: svc_setup_socket %p\n", sock);
if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { svsk = kzalloc(sizeof(*svsk), GFP_KERNEL);
*errp = -ENOMEM; if (!svsk)
return NULL; return ERR_PTR(-ENOMEM);
}
inet = sock->sk; inet = sock->sk;
/* Register socket with portmapper */ /* Register socket with portmapper */
if (*errp >= 0 && pmap_register) if (pmap_register)
*errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, err = svc_register(serv, sock_net(sock->sk), inet->sk_family,
inet->sk_protocol, inet->sk_protocol,
ntohs(inet_sk(inet)->inet_sport)); ntohs(inet_sk(inet)->inet_sport));
if (*errp < 0) { if (err < 0) {
kfree(svsk); kfree(svsk);
return NULL; return ERR_PTR(err);
} }
inet->sk_user_data = svsk; inet->sk_user_data = svsk;
...@@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, ...@@ -1450,42 +1399,38 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
int err = 0; int err = 0;
struct socket *so = sockfd_lookup(fd, &err); struct socket *so = sockfd_lookup(fd, &err);
struct svc_sock *svsk = NULL; struct svc_sock *svsk = NULL;
struct sockaddr_storage addr;
struct sockaddr *sin = (struct sockaddr *)&addr;
int salen;
if (!so) if (!so)
return err; return err;
err = -EAFNOSUPPORT;
if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
err = -EAFNOSUPPORT; goto out;
else if (so->sk->sk_protocol != IPPROTO_TCP && err = -EPROTONOSUPPORT;
if (so->sk->sk_protocol != IPPROTO_TCP &&
so->sk->sk_protocol != IPPROTO_UDP) so->sk->sk_protocol != IPPROTO_UDP)
err = -EPROTONOSUPPORT; goto out;
else if (so->state > SS_UNCONNECTED) err = -EISCONN;
err = -EISCONN; if (so->state > SS_UNCONNECTED)
else { goto out;
if (!try_module_get(THIS_MODULE)) err = -ENOENT;
err = -ENOENT; if (!try_module_get(THIS_MODULE))
else goto out;
svsk = svc_setup_socket(serv, so, &err, svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS);
SVC_SOCK_DEFAULTS); if (IS_ERR(svsk)) {
if (svsk) { module_put(THIS_MODULE);
struct sockaddr_storage addr; err = PTR_ERR(svsk);
struct sockaddr *sin = (struct sockaddr *)&addr; goto out;
int salen;
if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags);
spin_lock_bh(&serv->sv_lock);
list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks);
spin_unlock_bh(&serv->sv_lock);
svc_xprt_received(&svsk->sk_xprt);
err = 0;
} else
module_put(THIS_MODULE);
}
if (err) {
sockfd_put(so);
return err;
} }
if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
svc_add_new_perm_xprt(serv, &svsk->sk_xprt);
return svc_one_sock_name(svsk, name_return, len); return svc_one_sock_name(svsk, name_return, len);
out:
sockfd_put(so);
return err;
} }
EXPORT_SYMBOL_GPL(svc_addsock); EXPORT_SYMBOL_GPL(svc_addsock);
...@@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, ...@@ -1563,11 +1508,13 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
goto bummer; goto bummer;
} }
if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { svsk = svc_setup_socket(serv, sock, flags);
svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); if (IS_ERR(svsk)) {
return (struct svc_xprt *)svsk; error = PTR_ERR(svsk);
goto bummer;
} }
svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
return (struct svc_xprt *)svsk;
bummer: bummer:
dprintk("svc: svc_create_socket error = %d\n", -error); dprintk("svc: svc_create_socket error = %d\n", -error);
sock_release(sock); sock_release(sock);
......
...@@ -578,10 +578,6 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird) ...@@ -578,10 +578,6 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird)
list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q);
spin_unlock_bh(&listen_xprt->sc_lock); spin_unlock_bh(&listen_xprt->sc_lock);
/*
* Can't use svc_xprt_received here because we are not on a
* rqstp thread
*/
set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags);
svc_xprt_enqueue(&listen_xprt->sc_xprt); svc_xprt_enqueue(&listen_xprt->sc_xprt);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment