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

Commit a9861b50 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFS: Don't clobber the attribute type in nfs_update_inode()
  NFS: Fix a umount race
  NFS: Fix an Oops when truncating a file
  NFS: Ensure that we handle NFS4ERR_STALE_STATEID correctly
  NFSv4.1: Don't call nfs4_schedule_state_recovery() unnecessarily
  NFSv4: Don't allow posix locking against servers that don't support it
  NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
  NFS: Avoid warnings when CONFIG_NFS_V4=n
  NFS: Make nfs_commitdata_release static
  NFS: Try to commit unstable writes in nfs_release_page()
  NFS: Fix a reference leak in nfs_wb_cancel_page()
parents aa16cd8d 9b4b3513
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -486,6 +486,8 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
{
{
	dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
	dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);


	if (gfp & __GFP_WAIT)
		nfs_wb_page(page->mapping->host, page);
	/* If PagePrivate() is set, then the page is not freeable */
	/* If PagePrivate() is set, then the page is not freeable */
	if (PagePrivate(page))
	if (PagePrivate(page))
		return 0;
		return 0;
+3 −1
Original line number Original line Diff line number Diff line
@@ -1261,8 +1261,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)


	if (fattr->valid & NFS_ATTR_FATTR_MODE) {
	if (fattr->valid & NFS_ATTR_FATTR_MODE) {
		if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
		if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
			umode_t newmode = inode->i_mode & S_IFMT;
			newmode |= fattr->mode & S_IALLUGO;
			inode->i_mode = newmode;
			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
			inode->i_mode = fattr->mode;
		}
		}
	} else if (server->caps & NFS_CAP_MODE)
	} else if (server->caps & NFS_CAP_MODE)
		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+2 −0
Original line number Original line Diff line number Diff line
@@ -146,6 +146,7 @@ enum {
	NFS_O_RDWR_STATE,		/* OPEN stateid has read/write state */
	NFS_O_RDWR_STATE,		/* OPEN stateid has read/write state */
	NFS_STATE_RECLAIM_REBOOT,	/* OPEN stateid server rebooted */
	NFS_STATE_RECLAIM_REBOOT,	/* OPEN stateid server rebooted */
	NFS_STATE_RECLAIM_NOGRACE,	/* OPEN stateid needs to recover state */
	NFS_STATE_RECLAIM_NOGRACE,	/* OPEN stateid needs to recover state */
	NFS_STATE_POSIX_LOCKS,		/* Posix locks are supported */
};
};


struct nfs4_state {
struct nfs4_state {
@@ -277,6 +278,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *);
extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state);
extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
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);
+58 −20
Original line number Original line Diff line number Diff line
@@ -249,19 +249,15 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
			if (state == NULL)
			if (state == NULL)
				break;
				break;
			nfs4_state_mark_reclaim_nograce(clp, state);
			nfs4_state_mark_reclaim_nograce(clp, state);
		case -NFS4ERR_STALE_CLIENTID:
			goto do_state_recovery;
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_EXPIRED:
			if (state == NULL)
			nfs4_schedule_state_recovery(clp);
			ret = nfs4_wait_clnt_recover(clp);
			if (ret == 0)
				exception->retry = 1;
#if !defined(CONFIG_NFS_V4_1)
			break;
#else /* !defined(CONFIG_NFS_V4_1) */
			if (!nfs4_has_session(server->nfs_client))
				break;
				break;
			/* FALLTHROUGH */
			nfs4_state_mark_reclaim_reboot(clp, state);
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_EXPIRED:
			goto do_state_recovery;
#if defined(CONFIG_NFS_V4_1)
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BAD_HIGH_SLOT:
		case -NFS4ERR_BAD_HIGH_SLOT:
@@ -274,7 +270,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
			nfs4_schedule_state_recovery(clp);
			nfs4_schedule_state_recovery(clp);
			exception->retry = 1;
			exception->retry = 1;
			break;
			break;
#endif /* !defined(CONFIG_NFS_V4_1) */
#endif /* defined(CONFIG_NFS_V4_1) */
		case -NFS4ERR_FILE_OPEN:
		case -NFS4ERR_FILE_OPEN:
			if (exception->timeout > HZ) {
			if (exception->timeout > HZ) {
				/* We have retried a decent amount, time to
				/* We have retried a decent amount, time to
@@ -293,6 +289,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
	}
	}
	/* We failed to handle the error */
	/* We failed to handle the error */
	return nfs4_map_errors(ret);
	return nfs4_map_errors(ret);
do_state_recovery:
	nfs4_schedule_state_recovery(clp);
	ret = nfs4_wait_clnt_recover(clp);
	if (ret == 0)
		exception->retry = 1;
	return ret;
}
}




@@ -1658,6 +1660,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
	status = PTR_ERR(state);
	status = PTR_ERR(state);
	if (IS_ERR(state))
	if (IS_ERR(state))
		goto err_opendata_put;
		goto err_opendata_put;
	if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0)
		set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
	nfs4_opendata_put(opendata);
	nfs4_opendata_put(opendata);
	nfs4_put_state_owner(sp);
	nfs4_put_state_owner(sp);
	*res = state;
	*res = state;
@@ -3422,15 +3426,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
			if (state == NULL)
			if (state == NULL)
				break;
				break;
			nfs4_state_mark_reclaim_nograce(clp, state);
			nfs4_state_mark_reclaim_nograce(clp, state);
		case -NFS4ERR_STALE_CLIENTID:
			goto do_state_recovery;
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_STALE_STATEID:
			if (state == NULL)
				break;
			nfs4_state_mark_reclaim_reboot(clp, state);
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_EXPIRED:
			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
			goto do_state_recovery;
			nfs4_schedule_state_recovery(clp);
			if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
				rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
			task->tk_status = 0;
			return -EAGAIN;
#if defined(CONFIG_NFS_V4_1)
#if defined(CONFIG_NFS_V4_1)
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BADSLOT:
@@ -3458,6 +3461,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
	}
	}
	task->tk_status = nfs4_map_errors(task->tk_status);
	task->tk_status = nfs4_map_errors(task->tk_status);
	return 0;
	return 0;
do_state_recovery:
	rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
	nfs4_schedule_state_recovery(clp);
	if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
		rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
	task->tk_status = 0;
	return -EAGAIN;
}
}


static int
static int
@@ -4088,6 +4098,28 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {
	.rpc_release = nfs4_lock_release,
	.rpc_release = nfs4_lock_release,
};
};


static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
{
	struct nfs_client *clp = server->nfs_client;
	struct nfs4_state *state = lsp->ls_state;

	switch (error) {
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_EXPIRED:
		if (new_lock_owner != 0 ||
		   (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
			nfs4_state_mark_reclaim_nograce(clp, state);
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
		break;
	case -NFS4ERR_STALE_STATEID:
		if (new_lock_owner != 0 ||
		    (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
			nfs4_state_mark_reclaim_reboot(clp, state);
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
	};
}

static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
{
{
	struct nfs4_lockdata *data;
	struct nfs4_lockdata *data;
@@ -4126,6 +4158,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
	ret = nfs4_wait_for_completion_rpc_task(task);
	ret = nfs4_wait_for_completion_rpc_task(task);
	if (ret == 0) {
	if (ret == 0) {
		ret = data->rpc_status;
		ret = data->rpc_status;
		if (ret)
			nfs4_handle_setlk_error(data->server, data->lsp,
					data->arg.new_lock_owner, ret);
	} else
	} else
		data->cancelled = 1;
		data->cancelled = 1;
	rpc_put_task(task);
	rpc_put_task(task);
@@ -4181,8 +4216,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
{
{
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_inode *nfsi = NFS_I(state->inode);
	unsigned char fl_flags = request->fl_flags;
	unsigned char fl_flags = request->fl_flags;
	int status;
	int status = -ENOLCK;


	if ((fl_flags & FL_POSIX) &&
			!test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
		goto out;
	/* Is this a delegated open? */
	/* Is this a delegated open? */
	status = nfs4_set_lock_state(state, request);
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
	if (status != 0)
+1 −1
Original line number Original line Diff line number Diff line
@@ -901,7 +901,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
	nfs4_schedule_state_manager(clp);
	nfs4_schedule_state_manager(clp);
}
}


static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
{
{


	set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
	set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
Loading