Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77041ed9 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid



flock locks want to be labelled using the process pid, while posix locks
want to be labelled using the fl_owner.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent d3c7b7cc
Loading
Loading
Loading
Loading
+13 −2
Original line number Original line Diff line number Diff line
@@ -142,10 +142,20 @@ enum {
 * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
 * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
 */
 */


struct nfs4_lock_owner {
	unsigned int lo_type;
#define NFS4_ANY_LOCK_TYPE	(0U)
#define NFS4_FLOCK_LOCK_TYPE	(1U << 0)
#define NFS4_POSIX_LOCK_TYPE	(1U << 1)
	union {
		fl_owner_t posix_owner;
		pid_t flock_owner;
	} lo_u;
};

struct nfs4_lock_state {
struct nfs4_lock_state {
	struct list_head	ls_locks;	/* Other lock stateids */
	struct list_head	ls_locks;	/* Other lock stateids */
	struct nfs4_state *	ls_state;	/* Pointer to open state */
	struct nfs4_state *	ls_state;	/* Pointer to open state */
	fl_owner_t		ls_owner;	/* POSIX lock owner */
#define NFS_LOCK_INITIALIZED 1
#define NFS_LOCK_INITIALIZED 1
	int			ls_flags;
	int			ls_flags;
	struct nfs_seqid_counter	ls_seqid;
	struct nfs_seqid_counter	ls_seqid;
@@ -153,6 +163,7 @@ struct nfs4_lock_state {
	struct nfs_unique_id	ls_id;
	struct nfs_unique_id	ls_id;
	nfs4_stateid		ls_stateid;
	nfs4_stateid		ls_stateid;
	atomic_t		ls_count;
	atomic_t		ls_count;
	struct nfs4_lock_owner	ls_owner;
};
};


/* bits for nfs4_state->flags */
/* bits for nfs4_state->flags */
@@ -310,7 +321,7 @@ extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
extern void nfs41_handle_recall_slot(struct nfs_client *clp);
extern void nfs41_handle_recall_slot(struct nfs_client *clp);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t);


extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
+1 −1
Original line number Original line Diff line number Diff line
@@ -1767,7 +1767,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
	if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
	if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
		/* Use that stateid */
		/* Use that stateid */
	} else if (state != NULL) {
	} else if (state != NULL) {
		nfs4_copy_stateid(&arg.stateid, state, current->files);
		nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid);
	} else
	} else
		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));


+35 −10
Original line number Original line Diff line number Diff line
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
 * that is compatible with current->files
 * that is compatible with current->files
 */
 */
static struct nfs4_lock_state *
static struct nfs4_lock_state *
__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
{
{
	struct nfs4_lock_state *pos;
	struct nfs4_lock_state *pos;
	list_for_each_entry(pos, &state->lock_states, ls_locks) {
	list_for_each_entry(pos, &state->lock_states, ls_locks) {
		if (pos->ls_owner != fl_owner)
		if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type)
			continue;
			continue;
		switch (pos->ls_owner.lo_type) {
		case NFS4_POSIX_LOCK_TYPE:
			if (pos->ls_owner.lo_u.posix_owner != fl_owner)
				continue;
			break;
		case NFS4_FLOCK_LOCK_TYPE:
			if (pos->ls_owner.lo_u.flock_owner != fl_pid)
				continue;
		}
		atomic_inc(&pos->ls_count);
		atomic_inc(&pos->ls_count);
		return pos;
		return pos;
	}
	}
@@ -619,7 +628,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 * exists, return an uninitialized one.
 * exists, return an uninitialized one.
 *
 *
 */
 */
static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
{
{
	struct nfs4_lock_state *lsp;
	struct nfs4_lock_state *lsp;
	struct nfs_client *clp = state->owner->so_server->nfs_client;
	struct nfs_client *clp = state->owner->so_server->nfs_client;
@@ -633,7 +642,18 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
	lsp->ls_seqid.sequence = &lsp->ls_sequence;
	lsp->ls_seqid.sequence = &lsp->ls_sequence;
	atomic_set(&lsp->ls_count, 1);
	atomic_set(&lsp->ls_count, 1);
	lsp->ls_state = state;
	lsp->ls_state = state;
	lsp->ls_owner = fl_owner;
	lsp->ls_owner.lo_type = type;
	switch (lsp->ls_owner.lo_type) {
	case NFS4_FLOCK_LOCK_TYPE:
		lsp->ls_owner.lo_u.flock_owner = fl_pid;
		break;
	case NFS4_POSIX_LOCK_TYPE:
		lsp->ls_owner.lo_u.posix_owner = fl_owner;
		break;
	default:
		kfree(lsp);
		return NULL;
	}
	spin_lock(&clp->cl_lock);
	spin_lock(&clp->cl_lock);
	nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
	nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
	spin_unlock(&clp->cl_lock);
	spin_unlock(&clp->cl_lock);
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
 * exists, return an uninitialized one.
 * exists, return an uninitialized one.
 *
 *
 */
 */
static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type)
{
{
	struct nfs4_lock_state *lsp, *new = NULL;
	struct nfs4_lock_state *lsp, *new = NULL;
	
	
	for(;;) {
	for(;;) {
		spin_lock(&state->state_lock);
		spin_lock(&state->state_lock);
		lsp = __nfs4_find_lock_state(state, owner);
		lsp = __nfs4_find_lock_state(state, owner, pid, type);
		if (lsp != NULL)
		if (lsp != NULL)
			break;
			break;
		if (new != NULL) {
		if (new != NULL) {
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
			break;
			break;
		}
		}
		spin_unlock(&state->state_lock);
		spin_unlock(&state->state_lock);
		new = nfs4_alloc_lock_state(state, owner);
		new = nfs4_alloc_lock_state(state, owner, pid, type);
		if (new == NULL)
		if (new == NULL)
			return NULL;
			return NULL;
	}
	}
@@ -730,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)


	if (fl->fl_ops != NULL)
	if (fl->fl_ops != NULL)
		return 0;
		return 0;
	lsp = nfs4_get_lock_state(state, fl->fl_owner);
	if (fl->fl_flags & FL_POSIX)
		lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE);
	else if (fl->fl_flags & FL_FLOCK)
		lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE);
	else
		return -EINVAL;
	if (lsp == NULL)
	if (lsp == NULL)
		return -ENOMEM;
		return -ENOMEM;
	fl->fl_u.nfs4_fl.owner = lsp;
	fl->fl_u.nfs4_fl.owner = lsp;
@@ -742,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 * Byte-range lock aware utility to initialize the stateid of read/write
 * Byte-range lock aware utility to initialize the stateid of read/write
 * requests.
 * requests.
 */
 */
void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
{
{
	struct nfs4_lock_state *lsp;
	struct nfs4_lock_state *lsp;
	int seq;
	int seq;
@@ -755,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
		return;
		return;


	spin_lock(&state->state_lock);
	spin_lock(&state->state_lock);
	lsp = __nfs4_find_lock_state(state, fl_owner);
	lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
	if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
	if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
		memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
		memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
	spin_unlock(&state->state_lock);
	spin_unlock(&state->state_lock);
+1 −1
Original line number Original line Diff line number Diff line
@@ -1361,7 +1361,7 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context


	p = reserve_space(xdr, NFS4_STATEID_SIZE);
	p = reserve_space(xdr, NFS4_STATEID_SIZE);
	if (ctx->state != NULL) {
	if (ctx->state != NULL) {
		nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner);
		nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid);
		xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
		xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
	} else
	} else
		xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
		xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);