forked from mirrors/linux
		
	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: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									d3c7b7ccc1
								
							
						
					
					
						commit
						77041ed9b4
					
				
					 4 changed files with 50 additions and 14 deletions
				
			
		| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue