mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
A mistake on my part caused me to tag my branch 6 commits too early,
missing Chuck's fixes for the problem with callbacks over GSS from multi-homed servers, and a smaller fix from Laura Abbott. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbftA8AAoJECebzXlCjuG+QPMQALieEKkX0YoqRhPz5G+RrWFy KgOBFAoiRcjFQD6wMt9FzD6qYEZqSJ+I2b+K5N3BkdyDDQu845iD0wK0zBGhMgLm 7ith85nphIMbe18+5jPorqAsI9RlfBQjiSGw1MEx5dicLQQzTObHL5q+l5jcWna4 jWS3yUKv1URpOsR1hIryw74ktSnhuH8n//zmntw8aWrCkq3hnXOZK/agtYxZ7Viv V3kiQsiNpL2FPRcHN7ejhLUTnRkkuD2iYKrzP/SpTT/JfdNEUXlMhKkAySogNpus nvR9X7hwta8Lgrt7PSB9ibFTXtCupmuICg5mbDWy6nXea2NvpB01QhnTzrlX17Eh Yfk/18z95b6Qs1v4m3SI8ESmyc6l5dMZozLudtHzifyCqooWZriEhCR1PlQfQ/FJ 4cYQ8U/qiMiZIJXL7N2wpSoSaWR5bqU1rXen29Np1WEDkiv4Nf5u2fsCXzv0ZH2C ReWpNkbnNxsNiKpp4geBZtlcSEU1pk+1PqE0MagTdBV3iptiUHRSP4jR7qLnc0zT J1lCvU7Fodnt9vNSxMpt2Jd6XxQ6xtx7n6aMQAiYFnXDs+hP2hPnJVCScnYW3L6R 2r1sHRKKeoOzCJ2thw+zu4lOwMm7WPkJPWAYfv90reWkiKoy2vG0S9P7wsNGoJuW fuEjB2b9pow1Ffynat6q =JnLK -----END PGP SIGNATURE----- Merge tag 'nfsd-4.19-1' of git://linux-nfs.org/~bfields/linux Pull nfsd updates from Bruce Fields: "Chuck Lever fixed a problem with NFSv4.0 callbacks over GSS from multi-homed servers. The only new feature is a minor bit of protocol (change_attr_type) which the client doesn't even use yet. Other than that, various bugfixes and cleanup" * tag 'nfsd-4.19-1' of git://linux-nfs.org/~bfields/linux: (27 commits) sunrpc: Add comment defining gssd upcall API keywords nfsd: Remove callback_cred nfsd: Use correct credential for NFSv4.0 callback with GSS sunrpc: Extract target name into svc_cred sunrpc: Enable the kernel to specify the hostname part of service principals sunrpc: Don't use stack buffer with scatterlist rpc: remove unneeded variable 'ret' in rdma_listen_handler nfsd: use true and false for boolean values nfsd: constify write_op[] fs/nfsd: Delete invalid assignment statements in nfsd4_decode_exchange_id NFSD: Handle full-length symlinks NFSD: Refactor the generic write vector fill helper svcrdma: Clean up Read chunk path svcrdma: Avoid releasing a page in svc_xprt_release() nfsd: Mark expected switch fall-through sunrpc: remove redundant variables 'checksumlen','blocksize' and 'data' nfsd: fix leaked file lock with nfs exported overlayfs nfsd: don't advertise a SCSI layout for an unsupported request_queue nfsd: fix corrupted reply to badly ordered compound nfsd: clarify check_op_ordering ...
This commit is contained in:
commit
9157141c95
30 changed files with 299 additions and 217 deletions
|
|
@ -187,7 +187,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
|
|||
continue;
|
||||
if (!rpc_cmp_addr(nlm_addr(block->b_host), addr))
|
||||
continue;
|
||||
if (nfs_compare_fh(NFS_FH(file_inode(fl_blocked->fl_file)) ,fh) != 0)
|
||||
if (nfs_compare_fh(NFS_FH(locks_inode(fl_blocked->fl_file)), fh) != 0)
|
||||
continue;
|
||||
/* Alright, we found a lock. Set the return status
|
||||
* and wake up the caller
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
|
|||
char *nodename = req->a_host->h_rpcclnt->cl_nodename;
|
||||
|
||||
nlmclnt_next_cookie(&argp->cookie);
|
||||
memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
|
||||
memcpy(&lock->fh, NFS_FH(locks_inode(fl->fl_file)), sizeof(struct nfs_fh));
|
||||
lock->caller = nodename;
|
||||
lock->oh.data = req->a_owner;
|
||||
lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
|
||||
|
|
|
|||
|
|
@ -405,8 +405,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
|
|||
__be32 ret;
|
||||
|
||||
dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
|
||||
file_inode(file->f_file)->i_sb->s_id,
|
||||
file_inode(file->f_file)->i_ino,
|
||||
locks_inode(file->f_file)->i_sb->s_id,
|
||||
locks_inode(file->f_file)->i_ino,
|
||||
lock->fl.fl_type, lock->fl.fl_pid,
|
||||
(long long)lock->fl.fl_start,
|
||||
(long long)lock->fl.fl_end,
|
||||
|
|
@ -511,8 +511,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
|
|||
__be32 ret;
|
||||
|
||||
dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
|
||||
file_inode(file->f_file)->i_sb->s_id,
|
||||
file_inode(file->f_file)->i_ino,
|
||||
locks_inode(file->f_file)->i_sb->s_id,
|
||||
locks_inode(file->f_file)->i_ino,
|
||||
lock->fl.fl_type,
|
||||
(long long)lock->fl.fl_start,
|
||||
(long long)lock->fl.fl_end);
|
||||
|
|
@ -566,8 +566,8 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
|
|||
int error;
|
||||
|
||||
dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
|
||||
file_inode(file->f_file)->i_sb->s_id,
|
||||
file_inode(file->f_file)->i_ino,
|
||||
locks_inode(file->f_file)->i_sb->s_id,
|
||||
locks_inode(file->f_file)->i_ino,
|
||||
lock->fl.fl_pid,
|
||||
(long long)lock->fl.fl_start,
|
||||
(long long)lock->fl.fl_end);
|
||||
|
|
@ -595,8 +595,8 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l
|
|||
int status = 0;
|
||||
|
||||
dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
|
||||
file_inode(file->f_file)->i_sb->s_id,
|
||||
file_inode(file->f_file)->i_ino,
|
||||
locks_inode(file->f_file)->i_sb->s_id,
|
||||
locks_inode(file->f_file)->i_ino,
|
||||
lock->fl.fl_pid,
|
||||
(long long)lock->fl.fl_start,
|
||||
(long long)lock->fl.fl_end);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
|
|||
|
||||
static inline void nlm_debug_print_file(char *msg, struct nlm_file *file)
|
||||
{
|
||||
struct inode *inode = file_inode(file->f_file);
|
||||
struct inode *inode = locks_inode(file->f_file);
|
||||
|
||||
dprintk("lockd: %s %s/%ld\n",
|
||||
msg, inode->i_sb->s_id, inode->i_ino);
|
||||
|
|
@ -414,7 +414,7 @@ nlmsvc_match_sb(void *datap, struct nlm_file *file)
|
|||
{
|
||||
struct super_block *sb = datap;
|
||||
|
||||
return sb == file_inode(file->f_file)->i_sb;
|
||||
return sb == locks_inode(file->f_file)->i_sb;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ struct nfsd_net {
|
|||
|
||||
time_t nfsd4_lease;
|
||||
time_t nfsd4_grace;
|
||||
bool somebody_reclaimed;
|
||||
|
||||
bool nfsd_net_up;
|
||||
bool lockd_up;
|
||||
|
|
|
|||
|
|
@ -202,7 +202,8 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
|
|||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
resp->committed = argp->stable;
|
||||
nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
|
||||
nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
|
||||
&argp->first, cnt);
|
||||
if (!nvecs)
|
||||
RETURN_STATUS(nfserr_io);
|
||||
nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
|
||||
|
|
@ -289,6 +290,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)
|
|||
RETURN_STATUS(nfserr_nametoolong);
|
||||
|
||||
argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
|
||||
page_address(rqstp->rq_arg.pages[0]),
|
||||
argp->tlen);
|
||||
if (IS_ERR(argp->tname))
|
||||
RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
|
||||
|
|
@ -302,6 +304,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)
|
|||
fh_init(&resp->fh, NFS3_FHSIZE);
|
||||
nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
|
||||
argp->tname, &resp->fh);
|
||||
kfree(argp->tname);
|
||||
RETURN_STATUS(nfserr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -746,30 +746,17 @@ static int max_cb_time(struct net *net)
|
|||
return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
|
||||
}
|
||||
|
||||
static struct rpc_cred *callback_cred;
|
||||
|
||||
int set_callback_cred(void)
|
||||
{
|
||||
if (callback_cred)
|
||||
return 0;
|
||||
callback_cred = rpc_lookup_machine_cred("nfs");
|
||||
if (!callback_cred)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_callback_cred(void)
|
||||
{
|
||||
if (callback_cred) {
|
||||
put_rpccred(callback_cred);
|
||||
callback_cred = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
|
||||
{
|
||||
if (clp->cl_minorversion == 0) {
|
||||
return get_rpccred(callback_cred);
|
||||
char *principal = clp->cl_cred.cr_targ_princ ?
|
||||
clp->cl_cred.cr_targ_princ : "nfs";
|
||||
struct rpc_cred *cred;
|
||||
|
||||
cred = rpc_lookup_machine_cred(principal);
|
||||
if (!IS_ERR(cred))
|
||||
get_rpccred(cred);
|
||||
return cred;
|
||||
} else {
|
||||
struct rpc_auth *auth = client->cl_auth;
|
||||
struct auth_cred acred = {};
|
||||
|
|
@ -980,6 +967,7 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
|
|||
break;
|
||||
case -ESERVERFAULT:
|
||||
++session->se_cb_seq_nr;
|
||||
/* Fall through */
|
||||
case 1:
|
||||
case -NFS4ERR_BADSESSION:
|
||||
nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
|
||||
|
|
|
|||
|
|
@ -133,27 +133,20 @@ void nfsd4_setup_layout_type(struct svc_export *exp)
|
|||
if (!(exp->ex_flags & NFSEXP_PNFS))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If flex file is configured, use it by default. Otherwise
|
||||
* check if the file system supports exporting a block-like layout.
|
||||
* If the block device supports reservations prefer the SCSI layout,
|
||||
* otherwise advertise the block layout.
|
||||
*/
|
||||
#ifdef CONFIG_NFSD_FLEXFILELAYOUT
|
||||
exp->ex_layout_types |= 1 << LAYOUT_FLEX_FILES;
|
||||
#endif
|
||||
#ifdef CONFIG_NFSD_BLOCKLAYOUT
|
||||
/* overwrite flex file layout selection if needed */
|
||||
if (sb->s_export_op->get_uuid &&
|
||||
sb->s_export_op->map_blocks &&
|
||||
sb->s_export_op->commit_blocks)
|
||||
exp->ex_layout_types |= 1 << LAYOUT_BLOCK_VOLUME;
|
||||
#endif
|
||||
#ifdef CONFIG_NFSD_SCSILAYOUT
|
||||
/* overwrite block layout selection if needed */
|
||||
if (sb->s_export_op->map_blocks &&
|
||||
sb->s_export_op->commit_blocks &&
|
||||
sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops)
|
||||
sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops &&
|
||||
blk_queue_scsi_passthrough(sb->s_bdev->bd_disk->queue))
|
||||
exp->ex_layout_types |= 1 << LAYOUT_SCSI;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
struct svc_fh *resfh = NULL;
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
bool reclaim = false;
|
||||
|
||||
dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
|
||||
(int)open->op_fname.len, open->op_fname.data,
|
||||
|
|
@ -424,6 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
if (status)
|
||||
goto out;
|
||||
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
|
||||
reclaim = true;
|
||||
case NFS4_OPEN_CLAIM_FH:
|
||||
case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
|
||||
status = do_open_fhandle(rqstp, cstate, open);
|
||||
|
|
@ -452,6 +454,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
WARN(status && open->op_created,
|
||||
"nfsd4_process_open2 failed to open newly-created file! status=%u\n",
|
||||
be32_to_cpu(status));
|
||||
if (reclaim && !status)
|
||||
nn->somebody_reclaimed = true;
|
||||
out:
|
||||
if (resfh && resfh != &cstate->current_fh) {
|
||||
fh_dup2(&cstate->current_fh, resfh);
|
||||
|
|
@ -982,24 +986,6 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
|
||||
{
|
||||
int i = 1;
|
||||
int buflen = write->wr_buflen;
|
||||
|
||||
vec[0].iov_base = write->wr_head.iov_base;
|
||||
vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
|
||||
buflen -= vec[0].iov_len;
|
||||
|
||||
while (buflen) {
|
||||
vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
|
||||
vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
|
||||
buflen -= vec[i].iov_len;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
union nfsd4_op_u *u)
|
||||
|
|
@ -1027,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
write->wr_how_written = write->wr_stable_how;
|
||||
gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
|
||||
|
||||
nvecs = fill_in_write_vector(rqstp->rq_vec, write);
|
||||
nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
|
||||
&write->wr_head, write->wr_buflen);
|
||||
if (!nvecs)
|
||||
return nfserr_io;
|
||||
WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
|
||||
|
||||
status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
|
||||
|
|
@ -1599,7 +1588,7 @@ static const char *nfsd4_op_name(unsigned opnum);
|
|||
*/
|
||||
static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
|
||||
{
|
||||
struct nfsd4_op *op = &args->ops[0];
|
||||
struct nfsd4_op *first_op = &args->ops[0];
|
||||
|
||||
/* These ordering requirements don't apply to NFSv4.0: */
|
||||
if (args->minorversion == 0)
|
||||
|
|
@ -1607,12 +1596,17 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
|
|||
/* This is weird, but OK, not our problem: */
|
||||
if (args->opcnt == 0)
|
||||
return nfs_ok;
|
||||
if (op->status == nfserr_op_illegal)
|
||||
if (first_op->status == nfserr_op_illegal)
|
||||
return nfs_ok;
|
||||
if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
|
||||
if (!(nfsd4_ops[first_op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
|
||||
return nfserr_op_not_in_session;
|
||||
if (op->opnum == OP_SEQUENCE)
|
||||
if (first_op->opnum == OP_SEQUENCE)
|
||||
return nfs_ok;
|
||||
/*
|
||||
* So first_op is something allowed outside a session, like
|
||||
* EXCHANGE_ID; but then it has to be the only op in the
|
||||
* compound:
|
||||
*/
|
||||
if (args->opcnt != 1)
|
||||
return nfserr_not_only_op;
|
||||
return nfs_ok;
|
||||
|
|
@ -1726,6 +1720,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
|||
if (status) {
|
||||
op = &args->ops[0];
|
||||
op->status = status;
|
||||
resp->opcnt = 1;
|
||||
goto encode_op;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1979,8 +1979,10 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
|
|||
target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
|
||||
target->cr_raw_principal = kstrdup(source->cr_raw_principal,
|
||||
GFP_KERNEL);
|
||||
if ((source->cr_principal && ! target->cr_principal) ||
|
||||
(source->cr_raw_principal && ! target->cr_raw_principal))
|
||||
target->cr_targ_princ = kstrdup(source->cr_targ_princ, GFP_KERNEL);
|
||||
if ((source->cr_principal && !target->cr_principal) ||
|
||||
(source->cr_raw_principal && !target->cr_raw_principal) ||
|
||||
(source->cr_targ_princ && !target->cr_targ_princ))
|
||||
return -ENOMEM;
|
||||
|
||||
target->cr_flavor = source->cr_flavor;
|
||||
|
|
@ -2057,6 +2059,7 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
|
|||
|| (!gid_eq(cr1->cr_gid, cr2->cr_gid))
|
||||
|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
|
||||
return false;
|
||||
/* XXX: check that cr_targ_princ fields match ? */
|
||||
if (cr1->cr_principal == cr2->cr_principal)
|
||||
return true;
|
||||
if (!cr1->cr_principal || !cr2->cr_principal)
|
||||
|
|
@ -2956,18 +2959,18 @@ out_no_session:
|
|||
return status;
|
||||
}
|
||||
|
||||
static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
|
||||
static bool nfsd4_compound_in_session(struct nfsd4_compound_state *cstate, struct nfs4_sessionid *sid)
|
||||
{
|
||||
if (!session)
|
||||
if (!cstate->session)
|
||||
return false;
|
||||
return !memcmp(sid, &session->se_sessionid, sizeof(*sid));
|
||||
return !memcmp(sid, &cstate->session->se_sessionid, sizeof(*sid));
|
||||
}
|
||||
|
||||
__be32
|
||||
nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate,
|
||||
union nfsd4_op_u *u)
|
||||
{
|
||||
struct nfsd4_destroy_session *sessionid = &u->destroy_session;
|
||||
struct nfs4_sessionid *sessionid = &u->destroy_session.sessionid;
|
||||
struct nfsd4_session *ses;
|
||||
__be32 status;
|
||||
int ref_held_by_me = 0;
|
||||
|
|
@ -2975,14 +2978,14 @@ nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate,
|
|||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
status = nfserr_not_only_op;
|
||||
if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
|
||||
if (nfsd4_compound_in_session(cstate, sessionid)) {
|
||||
if (!nfsd4_last_compound_op(r))
|
||||
goto out;
|
||||
ref_held_by_me++;
|
||||
}
|
||||
dump_sessionid(__func__, &sessionid->sessionid);
|
||||
dump_sessionid(__func__, sessionid);
|
||||
spin_lock(&nn->client_lock);
|
||||
ses = find_in_sessionid_hashtbl(&sessionid->sessionid, net, &status);
|
||||
ses = find_in_sessionid_hashtbl(sessionid, net, &status);
|
||||
if (!ses)
|
||||
goto out_client_lock;
|
||||
status = nfserr_wrong_cred;
|
||||
|
|
@ -3945,9 +3948,9 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
|
|||
/*
|
||||
* We're assuming the state code never drops its reference
|
||||
* without first removing the lease. Since we're in this lease
|
||||
* callback (and since the lease code is serialized by the kernel
|
||||
* lock) we know the server hasn't removed the lease yet, we know
|
||||
* it's safe to take a reference.
|
||||
* callback (and since the lease code is serialized by the
|
||||
* i_lock) we know the server hasn't removed the lease yet, and
|
||||
* we know it's safe to take a reference.
|
||||
*/
|
||||
refcount_inc(&dp->dl_stid.sc_count);
|
||||
nfsd4_run_cb(&dp->dl_recall);
|
||||
|
|
@ -4693,6 +4696,28 @@ nfsd4_end_grace(struct nfsd_net *nn)
|
|||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've waited a lease period but there are still clients trying to
|
||||
* reclaim, wait a little longer to give them a chance to finish.
|
||||
*/
|
||||
static bool clients_still_reclaiming(struct nfsd_net *nn)
|
||||
{
|
||||
unsigned long now = get_seconds();
|
||||
unsigned long double_grace_period_end = nn->boot_time +
|
||||
2 * nn->nfsd4_lease;
|
||||
|
||||
if (!nn->somebody_reclaimed)
|
||||
return false;
|
||||
nn->somebody_reclaimed = false;
|
||||
/*
|
||||
* If we've given them *two* lease times to reclaim, and they're
|
||||
* still not done, give up:
|
||||
*/
|
||||
if (time_after(now, double_grace_period_end))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static time_t
|
||||
nfs4_laundromat(struct nfsd_net *nn)
|
||||
{
|
||||
|
|
@ -4706,6 +4731,11 @@ nfs4_laundromat(struct nfsd_net *nn)
|
|||
time_t t, new_timeo = nn->nfsd4_lease;
|
||||
|
||||
dprintk("NFSD: laundromat service - starting\n");
|
||||
|
||||
if (clients_still_reclaiming(nn)) {
|
||||
new_timeo = 0;
|
||||
goto out;
|
||||
}
|
||||
nfsd4_end_grace(nn);
|
||||
INIT_LIST_HEAD(&reaplist);
|
||||
spin_lock(&nn->client_lock);
|
||||
|
|
@ -4803,7 +4833,7 @@ nfs4_laundromat(struct nfsd_net *nn)
|
|||
posix_unblock_lock(&nbl->nbl_lock);
|
||||
free_blocked_lock(nbl);
|
||||
}
|
||||
|
||||
out:
|
||||
new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
|
||||
return new_timeo;
|
||||
}
|
||||
|
|
@ -6053,6 +6083,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
case 0: /* success! */
|
||||
nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
|
||||
status = 0;
|
||||
if (lock->lk_reclaim)
|
||||
nn->somebody_reclaimed = true;
|
||||
break;
|
||||
case FILE_LOCK_DEFERRED:
|
||||
nbl = NULL;
|
||||
|
|
@ -6293,7 +6325,7 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
|
|||
return status;
|
||||
}
|
||||
|
||||
inode = file_inode(filp);
|
||||
inode = locks_inode(filp);
|
||||
flctx = inode->i_flctx;
|
||||
|
||||
if (flctx && !list_empty_careful(&flctx->flc_posix)) {
|
||||
|
|
@ -7199,14 +7231,10 @@ nfs4_state_start(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = set_callback_cred();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
|
||||
if (laundry_wq == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_cleanup_cred;
|
||||
goto out;
|
||||
}
|
||||
ret = nfsd4_create_callback_queue();
|
||||
if (ret)
|
||||
|
|
@ -7217,8 +7245,7 @@ nfs4_state_start(void)
|
|||
|
||||
out_free_laundry:
|
||||
destroy_workqueue(laundry_wq);
|
||||
out_cleanup_cred:
|
||||
cleanup_callback_cred();
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -7255,7 +7282,6 @@ nfs4_state_shutdown(void)
|
|||
{
|
||||
destroy_workqueue(laundry_wq);
|
||||
nfsd4_destroy_callback_queue();
|
||||
cleanup_callback_cred();
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -1390,10 +1390,8 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
|
|||
p += XDR_QUADLEN(dummy);
|
||||
}
|
||||
|
||||
/* ssp_window and ssp_num_gss_handles */
|
||||
/* ignore ssp_window and ssp_num_gss_handles: */
|
||||
READ_BUF(8);
|
||||
dummy = be32_to_cpup(p++);
|
||||
dummy = be32_to_cpup(p++);
|
||||
break;
|
||||
default:
|
||||
goto xdr_error;
|
||||
|
|
@ -2006,6 +2004,31 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
|
|||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* ctime (in NFSv4, time_metadata) is not writeable, and the client
|
||||
* doesn't really care what resolution could theoretically be stored by
|
||||
* the filesystem.
|
||||
*
|
||||
* The client cares how close together changes can be while still
|
||||
* guaranteeing ctime changes. For most filesystems (which have
|
||||
* timestamps with nanosecond fields) that is limited by the resolution
|
||||
* of the time returned from current_time() (which I'm assuming to be
|
||||
* 1/HZ).
|
||||
*/
|
||||
static __be32 *encode_time_delta(__be32 *p, struct inode *inode)
|
||||
{
|
||||
struct timespec ts;
|
||||
u32 ns;
|
||||
|
||||
ns = max_t(u32, NSEC_PER_SEC/HZ, inode->i_sb->s_time_gran);
|
||||
ts = ns_to_timespec(ns);
|
||||
|
||||
p = xdr_encode_hyper(p, ts.tv_sec);
|
||||
*p++ = cpu_to_be32(ts.tv_nsec);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c)
|
||||
{
|
||||
*p++ = cpu_to_be32(c->atomic);
|
||||
|
|
@ -2797,9 +2820,7 @@ out_acl:
|
|||
p = xdr_reserve_space(xdr, 12);
|
||||
if (!p)
|
||||
goto out_resource;
|
||||
*p++ = cpu_to_be32(0);
|
||||
*p++ = cpu_to_be32(1);
|
||||
*p++ = cpu_to_be32(0);
|
||||
p = encode_time_delta(p, d_inode(dentry));
|
||||
}
|
||||
if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
|
||||
p = xdr_reserve_space(xdr, 12);
|
||||
|
|
@ -2868,6 +2889,16 @@ out_acl:
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (bmval2 & FATTR4_WORD2_CHANGE_ATTR_TYPE) {
|
||||
p = xdr_reserve_space(xdr, 4);
|
||||
if (!p)
|
||||
goto out_resource;
|
||||
if (IS_I_VERSION(d_inode(dentry)))
|
||||
*p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR);
|
||||
else
|
||||
*p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA);
|
||||
}
|
||||
|
||||
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
|
||||
status = nfsd4_encode_security_label(xdr, rqstp, context,
|
||||
contextlen);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
|
|||
static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
|
||||
#endif
|
||||
|
||||
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
|
||||
static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
|
||||
[NFSD_Fh] = write_filehandle,
|
||||
[NFSD_FO_UnlockIP] = write_unlock_ip,
|
||||
[NFSD_FO_UnlockFS] = write_unlock_fs,
|
||||
|
|
@ -1237,8 +1237,9 @@ static __net_init int nfsd_init_net(struct net *net)
|
|||
retval = nfsd_idmap_init(net);
|
||||
if (retval)
|
||||
goto out_idmap_error;
|
||||
nn->nfsd4_lease = 90; /* default lease time */
|
||||
nn->nfsd4_grace = 90;
|
||||
nn->nfsd4_lease = 45; /* default lease time */
|
||||
nn->nfsd4_grace = 45;
|
||||
nn->somebody_reclaimed = false;
|
||||
nn->clverifier_counter = prandom_u32();
|
||||
nn->clientid_counter = prandom_u32();
|
||||
|
||||
|
|
|
|||
|
|
@ -360,6 +360,7 @@ void nfsd_lockd_shutdown(void);
|
|||
|
||||
#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
|
||||
(NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
|
||||
FATTR4_WORD2_CHANGE_ATTR_TYPE | \
|
||||
FATTR4_WORD2_MODE_UMASK | \
|
||||
NFSD4_2_SECURITY_ATTRS)
|
||||
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
|
|||
switch (fsid_type) {
|
||||
case FSID_DEV:
|
||||
if (!old_valid_dev(exp_sb(exp)->s_dev))
|
||||
return 0;
|
||||
return false;
|
||||
/* FALL THROUGH */
|
||||
case FSID_MAJOR_MINOR:
|
||||
case FSID_ENCODE_DEV:
|
||||
|
|
@ -461,13 +461,13 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
|
|||
case FSID_UUID8:
|
||||
case FSID_UUID16:
|
||||
if (!is_root_export(exp))
|
||||
return 0;
|
||||
return false;
|
||||
/* fall through */
|
||||
case FSID_UUID4_INUM:
|
||||
case FSID_UUID16_INUM:
|
||||
return exp->ex_uuid != NULL;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,8 @@ nfsd_proc_write(struct svc_rqst *rqstp)
|
|||
SVCFH_fmt(&argp->fh),
|
||||
argp->len, argp->offset);
|
||||
|
||||
nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
|
||||
nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
|
||||
&argp->first, cnt);
|
||||
if (!nvecs)
|
||||
return nfserr_io;
|
||||
nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
|
||||
|
|
@ -453,6 +454,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)
|
|||
return nfserr_nametoolong;
|
||||
|
||||
argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
|
||||
page_address(rqstp->rq_arg.pages[0]),
|
||||
argp->tlen);
|
||||
if (IS_ERR(argp->tname))
|
||||
return nfserrno(PTR_ERR(argp->tname));
|
||||
|
|
@ -465,6 +467,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)
|
|||
nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
|
||||
argp->tname, &newfh);
|
||||
|
||||
kfree(argp->tname);
|
||||
fh_put(&argp->ffh);
|
||||
fh_put(&newfh);
|
||||
return nfserr;
|
||||
|
|
|
|||
|
|
@ -617,8 +617,6 @@ extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
|
|||
struct nfsd_net *nn);
|
||||
extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
|
||||
struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
|
||||
extern int set_callback_cred(void);
|
||||
extern void cleanup_callback_cred(void);
|
||||
extern void nfsd4_probe_callback(struct nfs4_client *clp);
|
||||
extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
|
||||
extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);
|
|||
|
||||
static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
|
||||
{
|
||||
return file_inode(file->f_file);
|
||||
return locks_inode(file->f_file);
|
||||
}
|
||||
|
||||
static inline int __nlm_privileged_request4(const struct sockaddr *sap)
|
||||
|
|
@ -359,7 +359,7 @@ static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
|
|||
static inline int nlm_compare_locks(const struct file_lock *fl1,
|
||||
const struct file_lock *fl2)
|
||||
{
|
||||
return file_inode(fl1->fl_file) == file_inode(fl2->fl_file)
|
||||
return locks_inode(fl1->fl_file) == locks_inode(fl2->fl_file)
|
||||
&& fl1->fl_pid == fl2->fl_pid
|
||||
&& fl1->fl_owner == fl2->fl_owner
|
||||
&& fl1->fl_start == fl2->fl_start
|
||||
|
|
|
|||
|
|
@ -374,6 +374,13 @@ enum lock_type4 {
|
|||
NFS4_WRITEW_LT = 4
|
||||
};
|
||||
|
||||
enum change_attr_type4 {
|
||||
NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR = 0,
|
||||
NFS4_CHANGE_TYPE_IS_VERSION_COUNTER = 1,
|
||||
NFS4_CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS = 2,
|
||||
NFS4_CHANGE_TYPE_IS_TIME_METADATA = 3,
|
||||
NFS4_CHANGE_TYPE_IS_UNDEFINED = 4
|
||||
};
|
||||
|
||||
/* Mandatory Attributes */
|
||||
#define FATTR4_WORD0_SUPPORTED_ATTRS (1UL << 0)
|
||||
|
|
@ -441,6 +448,7 @@ enum lock_type4 {
|
|||
#define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1)
|
||||
#define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4)
|
||||
#define FATTR4_WORD2_CLONE_BLKSIZE (1UL << 13)
|
||||
#define FATTR4_WORD2_CHANGE_ATTR_TYPE (1UL << 15)
|
||||
#define FATTR4_WORD2_SECURITY_LABEL (1UL << 16)
|
||||
#define FATTR4_WORD2_MODE_UMASK (1UL << 17)
|
||||
|
||||
|
|
|
|||
|
|
@ -496,9 +496,11 @@ void svc_reserve(struct svc_rqst *rqstp, int space);
|
|||
struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu);
|
||||
char * svc_print_addr(struct svc_rqst *, char *, size_t);
|
||||
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
|
||||
struct page **pages,
|
||||
struct kvec *first, size_t total);
|
||||
char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
|
||||
struct kvec *first, size_t total);
|
||||
struct kvec *first, void *p,
|
||||
size_t total);
|
||||
|
||||
#define RPC_MAX_ADDRBUFLEN (63U)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct svc_cred {
|
|||
/* name of form servicetype@hostname, passed down by
|
||||
* rpc.svcgssd, or computed from the above: */
|
||||
char *cr_principal;
|
||||
char *cr_targ_princ;
|
||||
struct gss_api_mech *cr_gss_mech;
|
||||
};
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ static inline void init_svc_cred(struct svc_cred *cred)
|
|||
cred->cr_group_info = NULL;
|
||||
cred->cr_raw_principal = NULL;
|
||||
cred->cr_principal = NULL;
|
||||
cred->cr_targ_princ = NULL;
|
||||
cred->cr_gss_mech = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +50,7 @@ static inline void free_svc_cred(struct svc_cred *cred)
|
|||
put_group_info(cred->cr_group_info);
|
||||
kfree(cred->cr_raw_principal);
|
||||
kfree(cred->cr_principal);
|
||||
kfree(cred->cr_targ_princ);
|
||||
gss_mech_put(cred->cr_gss_mech);
|
||||
init_svc_cred(cred);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue