You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-2.6.36' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.36' of git://linux-nfs.org/~bfields/linux: (34 commits) nfsd4: fix file open accounting for RDWR opens nfsd: don't allow setting maxblksize after svc created nfsd: initialize nfsd versions before creating svc net: sunrpc: removed duplicated #include nfsd41: Fix a crash when a callback is retried nfsd: fix startup/shutdown order bug nfsd: minor nfsd read api cleanup gcc-4.6: nfsd: fix initialized but not read warnings nfsd4: share file descriptors between stateid's nfsd4: fix openmode checking on IO using lock stateid nfsd4: miscellaneous process_open2 cleanup nfsd4: don't pretend to support write delegations nfsd: bypass readahead cache when have struct file nfsd: minor nfsd_svc() cleanup nfsd: move more into nfsd_startup() nfsd: just keep single lockd reference for nfsd nfsd: clean up nfsd_create_serv error handling nfsd: fix error handling in __write_ports_addxprt nfsd: fix error handling when starting nfsd with rpcbind down nfsd4: fix v4 state shutdown error paths ...
This commit is contained in:
+5
-3
@@ -168,7 +168,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
|
||||
svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
|
||||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = nfsd_read(rqstp, &resp->fh, NULL,
|
||||
nfserr = nfsd_read(rqstp, &resp->fh,
|
||||
argp->offset,
|
||||
rqstp->rq_vec, argp->vlen,
|
||||
&resp->count);
|
||||
@@ -271,7 +271,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
|
||||
fh_init(&resp->fh, NFS3_FHSIZE);
|
||||
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
|
||||
&argp->attrs, S_IFDIR, 0, &resp->fh);
|
||||
|
||||
fh_unlock(&resp->dirfh);
|
||||
RETURN_STATUS(nfserr);
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
|
||||
type = nfs3_ftypes[argp->ftype];
|
||||
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
|
||||
&argp->attrs, type, rdev, &resp->fh);
|
||||
|
||||
fh_unlock(&resp->dirfh);
|
||||
RETURN_STATUS(nfserr);
|
||||
}
|
||||
|
||||
@@ -348,6 +348,7 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
|
||||
/* Unlink. -S_IFDIR means file must not be a directory */
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
|
||||
fh_unlock(&resp->fh);
|
||||
RETURN_STATUS(nfserr);
|
||||
}
|
||||
|
||||
@@ -367,6 +368,7 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
|
||||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
|
||||
fh_unlock(&resp->fh);
|
||||
RETURN_STATUS(nfserr);
|
||||
}
|
||||
|
||||
|
||||
+34
-27
@@ -143,8 +143,6 @@ struct nfs4_cb_compound_hdr {
|
||||
u32 minorversion;
|
||||
/* res */
|
||||
int status;
|
||||
u32 taglen;
|
||||
char *tag;
|
||||
};
|
||||
|
||||
static struct {
|
||||
@@ -204,6 +202,16 @@ nfs_cb_stat_to_errno(int stat)
|
||||
* XDR encode
|
||||
*/
|
||||
|
||||
static void
|
||||
encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
|
||||
{
|
||||
__be32 *p;
|
||||
|
||||
RESERVE_SPACE(sizeof(stateid_t));
|
||||
WRITE32(sid->si_generation);
|
||||
WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
|
||||
}
|
||||
|
||||
static void
|
||||
encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
|
||||
{
|
||||
@@ -229,10 +237,10 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
|
||||
__be32 *p;
|
||||
int len = dp->dl_fh.fh_size;
|
||||
|
||||
RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len);
|
||||
RESERVE_SPACE(4);
|
||||
WRITE32(OP_CB_RECALL);
|
||||
WRITE32(dp->dl_stateid.si_generation);
|
||||
WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t));
|
||||
encode_stateid(xdr, &dp->dl_stateid);
|
||||
RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2));
|
||||
WRITE32(0); /* truncate optimization not implemented */
|
||||
WRITE32(len);
|
||||
WRITEMEM(&dp->dl_fh.fh_base, len);
|
||||
@@ -293,13 +301,14 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
|
||||
static int
|
||||
decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
|
||||
__be32 *p;
|
||||
u32 taglen;
|
||||
|
||||
READ_BUF(8);
|
||||
READ32(hdr->status);
|
||||
READ32(hdr->taglen);
|
||||
READ_BUF(hdr->taglen + 4);
|
||||
hdr->tag = (char *)p;
|
||||
p += XDR_QUADLEN(hdr->taglen);
|
||||
/* We've got no use for the tag; ignore it: */
|
||||
READ32(taglen);
|
||||
READ_BUF(taglen + 4);
|
||||
p += XDR_QUADLEN(taglen);
|
||||
READ32(hdr->nops);
|
||||
return 0;
|
||||
}
|
||||
@@ -667,28 +676,28 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
|
||||
}
|
||||
|
||||
switch (task->tk_status) {
|
||||
case -EIO:
|
||||
/* Network partition? */
|
||||
atomic_set(&clp->cl_cb_set, 0);
|
||||
warn_no_callback_path(clp, task->tk_status);
|
||||
if (current_rpc_client != task->tk_client) {
|
||||
/* queue a callback on the new connection: */
|
||||
nfsd4_cb_recall(dp);
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
return;
|
||||
case -EBADHANDLE:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
/* Race: client probably got cb_recall
|
||||
* before open reply granting delegation */
|
||||
break;
|
||||
default:
|
||||
/* success, or error we can't handle */
|
||||
return;
|
||||
/* Network partition? */
|
||||
atomic_set(&clp->cl_cb_set, 0);
|
||||
warn_no_callback_path(clp, task->tk_status);
|
||||
if (current_rpc_client != task->tk_client) {
|
||||
/* queue a callback on the new connection: */
|
||||
atomic_inc(&dp->dl_count);
|
||||
nfsd4_cb_recall(dp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dp->dl_retries--) {
|
||||
rpc_delay(task, 2*HZ);
|
||||
task->tk_status = 0;
|
||||
rpc_restart_call(task);
|
||||
rpc_restart_call_prepare(task);
|
||||
return;
|
||||
} else {
|
||||
atomic_set(&clp->cl_cb_set, 0);
|
||||
@@ -752,18 +761,16 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
|
||||
.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
|
||||
.rpc_cred = callback_cred
|
||||
};
|
||||
int status;
|
||||
|
||||
if (clnt == NULL)
|
||||
if (clnt == NULL) {
|
||||
nfs4_put_delegation(dp);
|
||||
return; /* Client is shutting down; give up. */
|
||||
}
|
||||
|
||||
args->args_op = dp;
|
||||
msg.rpc_argp = args;
|
||||
dp->dl_retries = 1;
|
||||
status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
|
||||
&nfsd4_cb_recall_ops, dp);
|
||||
if (status)
|
||||
nfs4_put_delegation(dp);
|
||||
rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
|
||||
}
|
||||
|
||||
void nfsd4_do_callback_rpc(struct work_struct *w)
|
||||
|
||||
+234
-145
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -2630,7 +2630,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
}
|
||||
read->rd_vlen = v;
|
||||
|
||||
nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
|
||||
nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp,
|
||||
read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
|
||||
&maxcount);
|
||||
|
||||
@@ -3325,6 +3325,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
|
||||
}
|
||||
/* Renew the clientid on success and on replay */
|
||||
release_session_client(cs->session);
|
||||
nfsd4_put_session(cs->session);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+11
-13
@@ -949,15 +949,12 @@ static ssize_t __write_ports_addfd(char *buf)
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
err = lockd_up();
|
||||
if (err != 0)
|
||||
goto out;
|
||||
|
||||
err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
|
||||
if (err < 0)
|
||||
lockd_down();
|
||||
if (err < 0) {
|
||||
svc_destroy(nfsd_serv);
|
||||
return err;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Decrease the count, but don't shut down the service */
|
||||
nfsd_serv->sv_nrthreads--;
|
||||
return err;
|
||||
@@ -978,9 +975,6 @@ static ssize_t __write_ports_delfd(char *buf)
|
||||
if (nfsd_serv != NULL)
|
||||
len = svc_sock_names(nfsd_serv, buf,
|
||||
SIMPLE_TRANSACTION_LIMIT, toclose);
|
||||
if (len >= 0)
|
||||
lockd_down();
|
||||
|
||||
kfree(toclose);
|
||||
return len;
|
||||
}
|
||||
@@ -1014,6 +1008,9 @@ static ssize_t __write_ports_addxprt(char *buf)
|
||||
PF_INET6, port, SVC_SOCK_ANONYMOUS);
|
||||
if (err < 0 && err != -EAFNOSUPPORT)
|
||||
goto out_close;
|
||||
|
||||
/* Decrease the count, but don't shut down the service */
|
||||
nfsd_serv->sv_nrthreads--;
|
||||
return 0;
|
||||
out_close:
|
||||
xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
|
||||
@@ -1022,8 +1019,7 @@ out_close:
|
||||
svc_xprt_put(xprt);
|
||||
}
|
||||
out_err:
|
||||
/* Decrease the count, but don't shut down the service */
|
||||
nfsd_serv->sv_nrthreads--;
|
||||
svc_destroy(nfsd_serv);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1194,7 +1190,7 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
|
||||
bsize = NFSSVC_MAXBLKSIZE;
|
||||
bsize &= ~(1024-1);
|
||||
mutex_lock(&nfsd_mutex);
|
||||
if (nfsd_serv && nfsd_serv->sv_nrthreads) {
|
||||
if (nfsd_serv) {
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -1310,6 +1306,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
|
||||
return -EINVAL;
|
||||
|
||||
status = nfs4_reset_recoverydir(recdir);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
|
||||
|
||||
@@ -153,6 +153,7 @@ void nfsd_lockd_shutdown(void);
|
||||
#define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID)
|
||||
#define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK)
|
||||
#define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME)
|
||||
#define nfserr_lock_range cpu_to_be32(NFSERR_LOCK_RANGE)
|
||||
#define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH)
|
||||
#define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP)
|
||||
#define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR)
|
||||
|
||||
+1
-3
@@ -144,7 +144,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
|
||||
svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
|
||||
|
||||
resp->count = argp->count;
|
||||
nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
|
||||
nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
|
||||
argp->offset,
|
||||
rqstp->rq_vec, argp->vlen,
|
||||
&resp->count);
|
||||
@@ -290,7 +290,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
|
||||
* gospel of sun micro
|
||||
*/
|
||||
if (type != S_IFREG) {
|
||||
int is_borc = 0;
|
||||
if (type != S_IFBLK && type != S_IFCHR) {
|
||||
rdev = 0;
|
||||
} else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
|
||||
@@ -298,7 +297,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
|
||||
type = S_IFIFO;
|
||||
} else {
|
||||
/* Okay, char or block special */
|
||||
is_borc = 1;
|
||||
if (!rdev)
|
||||
rdev = wanted;
|
||||
}
|
||||
|
||||
+96
-57
@@ -180,15 +180,80 @@ int nfsd_nrthreads(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int nfsd_init_socks(int port)
|
||||
{
|
||||
int error;
|
||||
if (!list_empty(&nfsd_serv->sv_permsocks))
|
||||
return 0;
|
||||
|
||||
error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
|
||||
SVC_SOCK_DEFAULTS);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
|
||||
SVC_SOCK_DEFAULTS);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool nfsd_up = false;
|
||||
|
||||
static int nfsd_startup(unsigned short port, int nrservs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (nfsd_up)
|
||||
return 0;
|
||||
/*
|
||||
* Readahead param cache - will no-op if it already exists.
|
||||
* (Note therefore results will be suboptimal if number of
|
||||
* threads is modified after nfsd start.)
|
||||
*/
|
||||
ret = nfsd_racache_init(2*nrservs);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nfsd_init_socks(port);
|
||||
if (ret)
|
||||
goto out_racache;
|
||||
ret = lockd_up();
|
||||
if (ret)
|
||||
goto out_racache;
|
||||
ret = nfs4_state_start();
|
||||
if (ret)
|
||||
goto out_lockd;
|
||||
nfsd_up = true;
|
||||
return 0;
|
||||
out_lockd:
|
||||
lockd_down();
|
||||
out_racache:
|
||||
nfsd_racache_shutdown();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nfsd_shutdown(void)
|
||||
{
|
||||
/*
|
||||
* write_ports can create the server without actually starting
|
||||
* any threads--if we get shut down before any threads are
|
||||
* started, then nfsd_last_thread will be run before any of this
|
||||
* other initialization has been done.
|
||||
*/
|
||||
if (!nfsd_up)
|
||||
return;
|
||||
nfs4_state_shutdown();
|
||||
lockd_down();
|
||||
nfsd_racache_shutdown();
|
||||
nfsd_up = false;
|
||||
}
|
||||
|
||||
static void nfsd_last_thread(struct svc_serv *serv)
|
||||
{
|
||||
/* When last nfsd thread exits we need to do some clean-up */
|
||||
struct svc_xprt *xprt;
|
||||
list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list)
|
||||
lockd_down();
|
||||
nfsd_serv = NULL;
|
||||
nfsd_racache_shutdown();
|
||||
nfs4_state_shutdown();
|
||||
nfsd_shutdown();
|
||||
|
||||
printk(KERN_WARNING "nfsd: last server has exited, flushing export "
|
||||
"cache\n");
|
||||
@@ -263,45 +328,18 @@ int nfsd_create_serv(void)
|
||||
nfsd_max_blksize >= 8*1024*2)
|
||||
nfsd_max_blksize /= 2;
|
||||
}
|
||||
nfsd_reset_versions();
|
||||
|
||||
nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
|
||||
nfsd_last_thread, nfsd, THIS_MODULE);
|
||||
if (nfsd_serv == NULL)
|
||||
err = -ENOMEM;
|
||||
else
|
||||
set_max_drc();
|
||||
return -ENOMEM;
|
||||
|
||||
set_max_drc();
|
||||
do_gettimeofday(&nfssvc_boot); /* record boot time */
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nfsd_init_socks(int port)
|
||||
{
|
||||
int error;
|
||||
if (!list_empty(&nfsd_serv->sv_permsocks))
|
||||
return 0;
|
||||
|
||||
error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
|
||||
SVC_SOCK_DEFAULTS);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = lockd_up();
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
|
||||
SVC_SOCK_DEFAULTS);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = lockd_up();
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfsd_nrpools(void)
|
||||
{
|
||||
if (nfsd_serv == NULL)
|
||||
@@ -376,10 +414,16 @@ int nfsd_set_nrthreads(int n, int *nthreads)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the number of threads and return the new number of threads.
|
||||
* This is also the function that starts the server if necessary, if
|
||||
* this is the first time nrservs is nonzero.
|
||||
*/
|
||||
int
|
||||
nfsd_svc(unsigned short port, int nrservs)
|
||||
{
|
||||
int error;
|
||||
bool nfsd_up_before;
|
||||
|
||||
mutex_lock(&nfsd_mutex);
|
||||
dprintk("nfsd: creating service\n");
|
||||
@@ -391,34 +435,29 @@ nfsd_svc(unsigned short port, int nrservs)
|
||||
if (nrservs == 0 && nfsd_serv == NULL)
|
||||
goto out;
|
||||
|
||||
/* Readahead param cache - will no-op if it already exists */
|
||||
error = nfsd_racache_init(2*nrservs);
|
||||
if (error<0)
|
||||
goto out;
|
||||
error = nfs4_state_start();
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
nfsd_reset_versions();
|
||||
|
||||
error = nfsd_create_serv();
|
||||
|
||||
if (error)
|
||||
goto out;
|
||||
error = nfsd_init_socks(port);
|
||||
if (error)
|
||||
goto failure;
|
||||
|
||||
nfsd_up_before = nfsd_up;
|
||||
|
||||
error = nfsd_startup(port, nrservs);
|
||||
if (error)
|
||||
goto out_destroy;
|
||||
error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
|
||||
if (error == 0)
|
||||
/* We are holding a reference to nfsd_serv which
|
||||
* we don't want to count in the return value,
|
||||
* so subtract 1
|
||||
*/
|
||||
error = nfsd_serv->sv_nrthreads - 1;
|
||||
failure:
|
||||
if (error)
|
||||
goto out_shutdown;
|
||||
/* We are holding a reference to nfsd_serv which
|
||||
* we don't want to count in the return value,
|
||||
* so subtract 1
|
||||
*/
|
||||
error = nfsd_serv->sv_nrthreads - 1;
|
||||
out_shutdown:
|
||||
if (error < 0 && !nfsd_up_before)
|
||||
nfsd_shutdown();
|
||||
out_destroy:
|
||||
svc_destroy(nfsd_serv); /* Release server */
|
||||
out:
|
||||
out:
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
+38
-2
@@ -88,7 +88,6 @@ struct nfs4_delegation {
|
||||
struct nfs4_client *dl_client;
|
||||
struct nfs4_file *dl_file;
|
||||
struct file_lock *dl_flock;
|
||||
struct file *dl_vfs_file;
|
||||
u32 dl_type;
|
||||
time_t dl_time;
|
||||
/* For recall: */
|
||||
@@ -342,12 +341,50 @@ struct nfs4_file {
|
||||
struct list_head fi_hash; /* hash by "struct inode *" */
|
||||
struct list_head fi_stateids;
|
||||
struct list_head fi_delegations;
|
||||
/* One each for O_RDONLY, O_WRONLY, O_RDWR: */
|
||||
struct file * fi_fds[3];
|
||||
/* One each for O_RDONLY, O_WRONLY: */
|
||||
atomic_t fi_access[2];
|
||||
/*
|
||||
* Each open stateid contributes 1 to either fi_readers or
|
||||
* fi_writers, or both, depending on the open mode. A
|
||||
* delegation also takes an fi_readers reference. Lock
|
||||
* stateid's take none.
|
||||
*/
|
||||
atomic_t fi_readers;
|
||||
atomic_t fi_writers;
|
||||
struct inode *fi_inode;
|
||||
u32 fi_id; /* used with stateowner->so_id
|
||||
* for stateid_hashtbl hash */
|
||||
bool fi_had_conflict;
|
||||
};
|
||||
|
||||
/* XXX: for first cut may fall back on returning file that doesn't work
|
||||
* at all? */
|
||||
static inline struct file *find_writeable_file(struct nfs4_file *f)
|
||||
{
|
||||
if (f->fi_fds[O_RDWR])
|
||||
return f->fi_fds[O_RDWR];
|
||||
return f->fi_fds[O_WRONLY];
|
||||
}
|
||||
|
||||
static inline struct file *find_readable_file(struct nfs4_file *f)
|
||||
{
|
||||
if (f->fi_fds[O_RDWR])
|
||||
return f->fi_fds[O_RDWR];
|
||||
return f->fi_fds[O_RDONLY];
|
||||
}
|
||||
|
||||
static inline struct file *find_any_file(struct nfs4_file *f)
|
||||
{
|
||||
if (f->fi_fds[O_RDWR])
|
||||
return f->fi_fds[O_RDWR];
|
||||
else if (f->fi_fds[O_RDWR])
|
||||
return f->fi_fds[O_WRONLY];
|
||||
else
|
||||
return f->fi_fds[O_RDONLY];
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs4_stateid can either be an open stateid or (eventually) a lock stateid
|
||||
*
|
||||
@@ -373,7 +410,6 @@ struct nfs4_stateid {
|
||||
struct nfs4_stateowner * st_stateowner;
|
||||
struct nfs4_file * st_file;
|
||||
stateid_t st_stateid;
|
||||
struct file * st_vfs_file;
|
||||
unsigned long st_access_bmap;
|
||||
unsigned long st_deny_bmap;
|
||||
struct nfs4_stateid * st_openstp;
|
||||
|
||||
+42
-37
@@ -604,7 +604,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_NFS_V4) */
|
||||
#endif /* defined(CONFIG_NFSD_V4) */
|
||||
|
||||
#ifdef CONFIG_NFSD_V3
|
||||
/*
|
||||
@@ -903,7 +903,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct raparms *ra;
|
||||
mm_segment_t oldfs;
|
||||
__be32 err;
|
||||
int host_err;
|
||||
@@ -914,12 +913,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
|
||||
goto out;
|
||||
|
||||
/* Get readahead parameters */
|
||||
ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
|
||||
|
||||
if (ra && ra->p_set)
|
||||
file->f_ra = ra->p_ra;
|
||||
|
||||
if (file->f_op->splice_read && rqstp->rq_splice_ok) {
|
||||
struct splice_desc sd = {
|
||||
.len = 0,
|
||||
@@ -937,16 +930,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
set_fs(oldfs);
|
||||
}
|
||||
|
||||
/* Write back readahead params */
|
||||
if (ra) {
|
||||
struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
|
||||
spin_lock(&rab->pb_lock);
|
||||
ra->p_ra = file->f_ra;
|
||||
ra->p_set = 1;
|
||||
ra->p_count--;
|
||||
spin_unlock(&rab->pb_lock);
|
||||
}
|
||||
|
||||
if (host_err >= 0) {
|
||||
nfsdstats.io_read += host_err;
|
||||
*count = host_err;
|
||||
@@ -1086,8 +1069,45 @@ out:
|
||||
* on entry. On return, *count contains the number of bytes actually read.
|
||||
* N.B. After this call fhp needs an fh_put
|
||||
*/
|
||||
__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
|
||||
{
|
||||
struct file *file;
|
||||
struct inode *inode;
|
||||
struct raparms *ra;
|
||||
__be32 err;
|
||||
|
||||
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
inode = file->f_path.dentry->d_inode;
|
||||
|
||||
/* Get readahead parameters */
|
||||
ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
|
||||
|
||||
if (ra && ra->p_set)
|
||||
file->f_ra = ra->p_ra;
|
||||
|
||||
err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
|
||||
|
||||
/* Write back readahead params */
|
||||
if (ra) {
|
||||
struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
|
||||
spin_lock(&rab->pb_lock);
|
||||
ra->p_ra = file->f_ra;
|
||||
ra->p_set = 1;
|
||||
ra->p_count--;
|
||||
spin_unlock(&rab->pb_lock);
|
||||
}
|
||||
|
||||
nfsd_close(file);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* As above, but use the provided file descriptor. */
|
||||
__be32
|
||||
nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
nfsd_read_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
loff_t offset, struct kvec *vec, int vlen,
|
||||
unsigned long *count)
|
||||
{
|
||||
@@ -1099,13 +1119,8 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
|
||||
if (err)
|
||||
goto out;
|
||||
err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
|
||||
} else {
|
||||
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
|
||||
if (err)
|
||||
goto out;
|
||||
err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
|
||||
nfsd_close(file);
|
||||
}
|
||||
} else /* Note file may still be NULL in NFSv4 special stateid case: */
|
||||
err = nfsd_read(rqstp, fhp, offset, vec, vlen, count);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@@ -1631,7 +1646,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
|
||||
char *name, int len, struct svc_fh *tfhp)
|
||||
{
|
||||
struct dentry *ddir, *dnew, *dold;
|
||||
struct inode *dirp, *dest;
|
||||
struct inode *dirp;
|
||||
__be32 err;
|
||||
int host_err;
|
||||
|
||||
@@ -1659,7 +1674,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
|
||||
goto out_nfserr;
|
||||
|
||||
dold = tfhp->fh_dentry;
|
||||
dest = dold->d_inode;
|
||||
|
||||
host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt);
|
||||
if (host_err) {
|
||||
@@ -2038,7 +2052,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
|
||||
struct dentry *dentry, int acc)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct path path;
|
||||
int err;
|
||||
|
||||
if (acc == NFSD_MAY_NOP)
|
||||
@@ -2111,15 +2124,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
|
||||
if (err == -EACCES && S_ISREG(inode->i_mode) &&
|
||||
acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
|
||||
err = inode_permission(inode, MAY_EXEC);
|
||||
if (err)
|
||||
goto nfsd_out;
|
||||
|
||||
/* Do integrity (permission) checking now, but defer incrementing
|
||||
* IMA counts to the actual file open.
|
||||
*/
|
||||
path.mnt = exp->ex_path.mnt;
|
||||
path.dentry = dentry;
|
||||
nfsd_out:
|
||||
return err? nfserrno(err) : 0;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -64,7 +64,9 @@ __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *,
|
||||
__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int,
|
||||
int, struct file **);
|
||||
void nfsd_close(struct file *);
|
||||
__be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
|
||||
__be32 nfsd_read(struct svc_rqst *, struct svc_fh *,
|
||||
loff_t, struct kvec *, int, unsigned long *);
|
||||
__be32 nfsd_read_file(struct svc_rqst *, struct svc_fh *, struct file *,
|
||||
loff_t, struct kvec *, int, unsigned long *);
|
||||
__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
|
||||
loff_t, struct kvec *,int, unsigned long *, int *);
|
||||
|
||||
@@ -192,6 +192,7 @@ extern int cache_check(struct cache_detail *detail,
|
||||
extern void cache_flush(void);
|
||||
extern void cache_purge(struct cache_detail *detail);
|
||||
#define NEVER (0x7FFFFFFF)
|
||||
extern void __init cache_initialize(void);
|
||||
extern int cache_register(struct cache_detail *cd);
|
||||
extern void cache_unregister(struct cache_detail *cd);
|
||||
|
||||
|
||||
+6
-2
@@ -34,7 +34,6 @@
|
||||
#include <linux/sunrpc/cache.h>
|
||||
#include <linux/sunrpc/stats.h>
|
||||
#include <linux/sunrpc/rpc_pipe_fs.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
#define RPCDBG_FACILITY RPCDBG_CACHE
|
||||
|
||||
@@ -320,7 +319,7 @@ static struct cache_detail *current_detail;
|
||||
static int current_index;
|
||||
|
||||
static void do_cache_clean(struct work_struct *work);
|
||||
static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean);
|
||||
static struct delayed_work cache_cleaner;
|
||||
|
||||
static void sunrpc_init_cache_detail(struct cache_detail *cd)
|
||||
{
|
||||
@@ -1504,6 +1503,11 @@ static int create_cache_proc_entries(struct cache_detail *cd)
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init cache_initialize(void)
|
||||
{
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean);
|
||||
}
|
||||
|
||||
int cache_register(struct cache_detail *cd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -44,6 +44,7 @@ init_sunrpc(void)
|
||||
#ifdef CONFIG_PROC_FS
|
||||
rpc_proc_init();
|
||||
#endif
|
||||
cache_initialize();
|
||||
cache_register(&ip_map_cache);
|
||||
cache_register(&unix_gid_cache);
|
||||
svc_init_xprt_sock(); /* svc sock transport */
|
||||
|
||||
Reference in New Issue
Block a user