diff options
author | David S. Miller <davem@davemloft.net> | 2011-01-24 16:17:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-24 16:17:06 -0500 |
commit | e92427b289d252cfbd4cb5282d92f4ce1a5bb1fb (patch) | |
tree | 6d30e5e7b7f8e9aaa51d43b7128ac56860fa03bb /fs/nfs/nfs4proc.c | |
parent | c506653d35249bb4738bb139c24362e1ae724bc1 (diff) | |
parent | ec30f343d61391ab23705e50a525da1d55395780 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 188 |
1 files changed, 128 insertions, 60 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4435e5e1f904..9d992b0346e3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/mount.h> | 49 | #include <linux/mount.h> |
50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
51 | #include <linux/sunrpc/bc_xprt.h> | 51 | #include <linux/sunrpc/bc_xprt.h> |
52 | #include <linux/xattr.h> | ||
52 | 53 | ||
53 | #include "nfs4_fs.h" | 54 | #include "nfs4_fs.h" |
54 | #include "delegation.h" | 55 | #include "delegation.h" |
@@ -355,9 +356,9 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot) | |||
355 | } | 356 | } |
356 | 357 | ||
357 | /* | 358 | /* |
358 | * Signal state manager thread if session is drained | 359 | * Signal state manager thread if session fore channel is drained |
359 | */ | 360 | */ |
360 | static void nfs41_check_drain_session_complete(struct nfs4_session *ses) | 361 | static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) |
361 | { | 362 | { |
362 | struct rpc_task *task; | 363 | struct rpc_task *task; |
363 | 364 | ||
@@ -371,8 +372,20 @@ static void nfs41_check_drain_session_complete(struct nfs4_session *ses) | |||
371 | if (ses->fc_slot_table.highest_used_slotid != -1) | 372 | if (ses->fc_slot_table.highest_used_slotid != -1) |
372 | return; | 373 | return; |
373 | 374 | ||
374 | dprintk("%s COMPLETE: Session Drained\n", __func__); | 375 | dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); |
375 | complete(&ses->complete); | 376 | complete(&ses->fc_slot_table.complete); |
377 | } | ||
378 | |||
379 | /* | ||
380 | * Signal state manager thread if session back channel is drained | ||
381 | */ | ||
382 | void nfs4_check_drain_bc_complete(struct nfs4_session *ses) | ||
383 | { | ||
384 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || | ||
385 | ses->bc_slot_table.highest_used_slotid != -1) | ||
386 | return; | ||
387 | dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); | ||
388 | complete(&ses->bc_slot_table.complete); | ||
376 | } | 389 | } |
377 | 390 | ||
378 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | 391 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
@@ -389,7 +402,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
389 | 402 | ||
390 | spin_lock(&tbl->slot_tbl_lock); | 403 | spin_lock(&tbl->slot_tbl_lock); |
391 | nfs4_free_slot(tbl, res->sr_slot); | 404 | nfs4_free_slot(tbl, res->sr_slot); |
392 | nfs41_check_drain_session_complete(res->sr_session); | 405 | nfs4_check_drain_fc_complete(res->sr_session); |
393 | spin_unlock(&tbl->slot_tbl_lock); | 406 | spin_unlock(&tbl->slot_tbl_lock); |
394 | res->sr_slot = NULL; | 407 | res->sr_slot = NULL; |
395 | } | 408 | } |
@@ -1826,6 +1839,8 @@ struct nfs4_closedata { | |||
1826 | struct nfs_closeres res; | 1839 | struct nfs_closeres res; |
1827 | struct nfs_fattr fattr; | 1840 | struct nfs_fattr fattr; |
1828 | unsigned long timestamp; | 1841 | unsigned long timestamp; |
1842 | bool roc; | ||
1843 | u32 roc_barrier; | ||
1829 | }; | 1844 | }; |
1830 | 1845 | ||
1831 | static void nfs4_free_closedata(void *data) | 1846 | static void nfs4_free_closedata(void *data) |
@@ -1833,6 +1848,8 @@ static void nfs4_free_closedata(void *data) | |||
1833 | struct nfs4_closedata *calldata = data; | 1848 | struct nfs4_closedata *calldata = data; |
1834 | struct nfs4_state_owner *sp = calldata->state->owner; | 1849 | struct nfs4_state_owner *sp = calldata->state->owner; |
1835 | 1850 | ||
1851 | if (calldata->roc) | ||
1852 | pnfs_roc_release(calldata->state->inode); | ||
1836 | nfs4_put_open_state(calldata->state); | 1853 | nfs4_put_open_state(calldata->state); |
1837 | nfs_free_seqid(calldata->arg.seqid); | 1854 | nfs_free_seqid(calldata->arg.seqid); |
1838 | nfs4_put_state_owner(sp); | 1855 | nfs4_put_state_owner(sp); |
@@ -1865,6 +1882,9 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1865 | */ | 1882 | */ |
1866 | switch (task->tk_status) { | 1883 | switch (task->tk_status) { |
1867 | case 0: | 1884 | case 0: |
1885 | if (calldata->roc) | ||
1886 | pnfs_roc_set_barrier(state->inode, | ||
1887 | calldata->roc_barrier); | ||
1868 | nfs_set_open_stateid(state, &calldata->res.stateid, 0); | 1888 | nfs_set_open_stateid(state, &calldata->res.stateid, 0); |
1869 | renew_lease(server, calldata->timestamp); | 1889 | renew_lease(server, calldata->timestamp); |
1870 | nfs4_close_clear_stateid_flags(state, | 1890 | nfs4_close_clear_stateid_flags(state, |
@@ -1917,8 +1937,15 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1917 | return; | 1937 | return; |
1918 | } | 1938 | } |
1919 | 1939 | ||
1920 | if (calldata->arg.fmode == 0) | 1940 | if (calldata->arg.fmode == 0) { |
1921 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; | 1941 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; |
1942 | if (calldata->roc && | ||
1943 | pnfs_roc_drain(calldata->inode, &calldata->roc_barrier)) { | ||
1944 | rpc_sleep_on(&NFS_SERVER(calldata->inode)->roc_rpcwaitq, | ||
1945 | task, NULL); | ||
1946 | return; | ||
1947 | } | ||
1948 | } | ||
1922 | 1949 | ||
1923 | nfs_fattr_init(calldata->res.fattr); | 1950 | nfs_fattr_init(calldata->res.fattr); |
1924 | calldata->timestamp = jiffies; | 1951 | calldata->timestamp = jiffies; |
@@ -1946,7 +1973,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
1946 | * | 1973 | * |
1947 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 1974 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
1948 | */ | 1975 | */ |
1949 | int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait) | 1976 | int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc) |
1950 | { | 1977 | { |
1951 | struct nfs_server *server = NFS_SERVER(state->inode); | 1978 | struct nfs_server *server = NFS_SERVER(state->inode); |
1952 | struct nfs4_closedata *calldata; | 1979 | struct nfs4_closedata *calldata; |
@@ -1981,11 +2008,12 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i | |||
1981 | calldata->res.fattr = &calldata->fattr; | 2008 | calldata->res.fattr = &calldata->fattr; |
1982 | calldata->res.seqid = calldata->arg.seqid; | 2009 | calldata->res.seqid = calldata->arg.seqid; |
1983 | calldata->res.server = server; | 2010 | calldata->res.server = server; |
2011 | calldata->roc = roc; | ||
1984 | path_get(path); | 2012 | path_get(path); |
1985 | calldata->path = *path; | 2013 | calldata->path = *path; |
1986 | 2014 | ||
1987 | msg.rpc_argp = &calldata->arg, | 2015 | msg.rpc_argp = &calldata->arg; |
1988 | msg.rpc_resp = &calldata->res, | 2016 | msg.rpc_resp = &calldata->res; |
1989 | task_setup_data.callback_data = calldata; | 2017 | task_setup_data.callback_data = calldata; |
1990 | task = rpc_run_task(&task_setup_data); | 2018 | task = rpc_run_task(&task_setup_data); |
1991 | if (IS_ERR(task)) | 2019 | if (IS_ERR(task)) |
@@ -1998,6 +2026,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i | |||
1998 | out_free_calldata: | 2026 | out_free_calldata: |
1999 | kfree(calldata); | 2027 | kfree(calldata); |
2000 | out: | 2028 | out: |
2029 | if (roc) | ||
2030 | pnfs_roc_release(state->inode); | ||
2001 | nfs4_put_open_state(state); | 2031 | nfs4_put_open_state(state); |
2002 | nfs4_put_state_owner(sp); | 2032 | nfs4_put_state_owner(sp); |
2003 | return status; | 2033 | return status; |
@@ -2486,6 +2516,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2486 | path = &ctx->path; | 2516 | path = &ctx->path; |
2487 | fmode = ctx->mode; | 2517 | fmode = ctx->mode; |
2488 | } | 2518 | } |
2519 | sattr->ia_mode &= ~current_umask(); | ||
2489 | state = nfs4_do_open(dir, path, fmode, flags, sattr, cred); | 2520 | state = nfs4_do_open(dir, path, fmode, flags, sattr, cred); |
2490 | d_drop(dentry); | 2521 | d_drop(dentry); |
2491 | if (IS_ERR(state)) { | 2522 | if (IS_ERR(state)) { |
@@ -2816,6 +2847,8 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
2816 | { | 2847 | { |
2817 | struct nfs4_exception exception = { }; | 2848 | struct nfs4_exception exception = { }; |
2818 | int err; | 2849 | int err; |
2850 | |||
2851 | sattr->ia_mode &= ~current_umask(); | ||
2819 | do { | 2852 | do { |
2820 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2853 | err = nfs4_handle_exception(NFS_SERVER(dir), |
2821 | _nfs4_proc_mkdir(dir, dentry, sattr), | 2854 | _nfs4_proc_mkdir(dir, dentry, sattr), |
@@ -2916,6 +2949,8 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
2916 | { | 2949 | { |
2917 | struct nfs4_exception exception = { }; | 2950 | struct nfs4_exception exception = { }; |
2918 | int err; | 2951 | int err; |
2952 | |||
2953 | sattr->ia_mode &= ~current_umask(); | ||
2919 | do { | 2954 | do { |
2920 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2955 | err = nfs4_handle_exception(NFS_SERVER(dir), |
2921 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), | 2956 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), |
@@ -3478,6 +3513,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3478 | struct nfs4_setclientid setclientid = { | 3513 | struct nfs4_setclientid setclientid = { |
3479 | .sc_verifier = &sc_verifier, | 3514 | .sc_verifier = &sc_verifier, |
3480 | .sc_prog = program, | 3515 | .sc_prog = program, |
3516 | .sc_cb_ident = clp->cl_cb_ident, | ||
3481 | }; | 3517 | }; |
3482 | struct rpc_message msg = { | 3518 | struct rpc_message msg = { |
3483 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], | 3519 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], |
@@ -3517,7 +3553,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3517 | if (signalled()) | 3553 | if (signalled()) |
3518 | break; | 3554 | break; |
3519 | if (loop++ & 1) | 3555 | if (loop++ & 1) |
3520 | ssleep(clp->cl_lease_time + 1); | 3556 | ssleep(clp->cl_lease_time / HZ + 1); |
3521 | else | 3557 | else |
3522 | if (++clp->cl_id_uniquifier == 0) | 3558 | if (++clp->cl_id_uniquifier == 0) |
3523 | break; | 3559 | break; |
@@ -3663,8 +3699,8 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3663 | data->rpc_status = 0; | 3699 | data->rpc_status = 0; |
3664 | 3700 | ||
3665 | task_setup_data.callback_data = data; | 3701 | task_setup_data.callback_data = data; |
3666 | msg.rpc_argp = &data->args, | 3702 | msg.rpc_argp = &data->args; |
3667 | msg.rpc_resp = &data->res, | 3703 | msg.rpc_resp = &data->res; |
3668 | task = rpc_run_task(&task_setup_data); | 3704 | task = rpc_run_task(&task_setup_data); |
3669 | if (IS_ERR(task)) | 3705 | if (IS_ERR(task)) |
3670 | return PTR_ERR(task); | 3706 | return PTR_ERR(task); |
@@ -3743,6 +3779,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
3743 | goto out; | 3779 | goto out; |
3744 | lsp = request->fl_u.nfs4_fl.owner; | 3780 | lsp = request->fl_u.nfs4_fl.owner; |
3745 | arg.lock_owner.id = lsp->ls_id.id; | 3781 | arg.lock_owner.id = lsp->ls_id.id; |
3782 | arg.lock_owner.s_dev = server->s_dev; | ||
3746 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 3783 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); |
3747 | switch (status) { | 3784 | switch (status) { |
3748 | case 0: | 3785 | case 0: |
@@ -3908,8 +3945,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
3908 | return ERR_PTR(-ENOMEM); | 3945 | return ERR_PTR(-ENOMEM); |
3909 | } | 3946 | } |
3910 | 3947 | ||
3911 | msg.rpc_argp = &data->arg, | 3948 | msg.rpc_argp = &data->arg; |
3912 | msg.rpc_resp = &data->res, | 3949 | msg.rpc_resp = &data->res; |
3913 | task_setup_data.callback_data = data; | 3950 | task_setup_data.callback_data = data; |
3914 | return rpc_run_task(&task_setup_data); | 3951 | return rpc_run_task(&task_setup_data); |
3915 | } | 3952 | } |
@@ -3988,6 +4025,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3988 | p->arg.lock_stateid = &lsp->ls_stateid; | 4025 | p->arg.lock_stateid = &lsp->ls_stateid; |
3989 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 4026 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
3990 | p->arg.lock_owner.id = lsp->ls_id.id; | 4027 | p->arg.lock_owner.id = lsp->ls_id.id; |
4028 | p->arg.lock_owner.s_dev = server->s_dev; | ||
3991 | p->res.lock_seqid = p->arg.lock_seqid; | 4029 | p->res.lock_seqid = p->arg.lock_seqid; |
3992 | p->lsp = lsp; | 4030 | p->lsp = lsp; |
3993 | p->server = server; | 4031 | p->server = server; |
@@ -4145,8 +4183,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4145 | data->arg.reclaim = NFS_LOCK_RECLAIM; | 4183 | data->arg.reclaim = NFS_LOCK_RECLAIM; |
4146 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; | 4184 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; |
4147 | } | 4185 | } |
4148 | msg.rpc_argp = &data->arg, | 4186 | msg.rpc_argp = &data->arg; |
4149 | msg.rpc_resp = &data->res, | 4187 | msg.rpc_resp = &data->res; |
4150 | task_setup_data.callback_data = data; | 4188 | task_setup_data.callback_data = data; |
4151 | task = rpc_run_task(&task_setup_data); | 4189 | task = rpc_run_task(&task_setup_data); |
4152 | if (IS_ERR(task)) | 4190 | if (IS_ERR(task)) |
@@ -4392,48 +4430,43 @@ void nfs4_release_lockowner(const struct nfs4_lock_state *lsp) | |||
4392 | return; | 4430 | return; |
4393 | args->lock_owner.clientid = server->nfs_client->cl_clientid; | 4431 | args->lock_owner.clientid = server->nfs_client->cl_clientid; |
4394 | args->lock_owner.id = lsp->ls_id.id; | 4432 | args->lock_owner.id = lsp->ls_id.id; |
4433 | args->lock_owner.s_dev = server->s_dev; | ||
4395 | msg.rpc_argp = args; | 4434 | msg.rpc_argp = args; |
4396 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args); | 4435 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args); |
4397 | } | 4436 | } |
4398 | 4437 | ||
4399 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" | 4438 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" |
4400 | 4439 | ||
4401 | int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, | 4440 | static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key, |
4402 | size_t buflen, int flags) | 4441 | const void *buf, size_t buflen, |
4442 | int flags, int type) | ||
4403 | { | 4443 | { |
4404 | struct inode *inode = dentry->d_inode; | 4444 | if (strcmp(key, "") != 0) |
4405 | 4445 | return -EINVAL; | |
4406 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) | ||
4407 | return -EOPNOTSUPP; | ||
4408 | 4446 | ||
4409 | return nfs4_proc_set_acl(inode, buf, buflen); | 4447 | return nfs4_proc_set_acl(dentry->d_inode, buf, buflen); |
4410 | } | 4448 | } |
4411 | 4449 | ||
4412 | /* The getxattr man page suggests returning -ENODATA for unknown attributes, | 4450 | static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key, |
4413 | * and that's what we'll do for e.g. user attributes that haven't been set. | 4451 | void *buf, size_t buflen, int type) |
4414 | * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported | ||
4415 | * attributes in kernel-managed attribute namespaces. */ | ||
4416 | ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf, | ||
4417 | size_t buflen) | ||
4418 | { | 4452 | { |
4419 | struct inode *inode = dentry->d_inode; | 4453 | if (strcmp(key, "") != 0) |
4420 | 4454 | return -EINVAL; | |
4421 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) | ||
4422 | return -EOPNOTSUPP; | ||
4423 | 4455 | ||
4424 | return nfs4_proc_get_acl(inode, buf, buflen); | 4456 | return nfs4_proc_get_acl(dentry->d_inode, buf, buflen); |
4425 | } | 4457 | } |
4426 | 4458 | ||
4427 | ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) | 4459 | static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, |
4460 | size_t list_len, const char *name, | ||
4461 | size_t name_len, int type) | ||
4428 | { | 4462 | { |
4429 | size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1; | 4463 | size_t len = sizeof(XATTR_NAME_NFSV4_ACL); |
4430 | 4464 | ||
4431 | if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode))) | 4465 | if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode))) |
4432 | return 0; | 4466 | return 0; |
4433 | if (buf && buflen < len) | 4467 | |
4434 | return -ERANGE; | 4468 | if (list && len <= list_len) |
4435 | if (buf) | 4469 | memcpy(list, XATTR_NAME_NFSV4_ACL, len); |
4436 | memcpy(buf, XATTR_NAME_NFSV4_ACL, len); | ||
4437 | return len; | 4470 | return len; |
4438 | } | 4471 | } |
4439 | 4472 | ||
@@ -4486,6 +4519,25 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4486 | 4519 | ||
4487 | #ifdef CONFIG_NFS_V4_1 | 4520 | #ifdef CONFIG_NFS_V4_1 |
4488 | /* | 4521 | /* |
4522 | * Check the exchange flags returned by the server for invalid flags, having | ||
4523 | * both PNFS and NON_PNFS flags set, and not having one of NON_PNFS, PNFS, or | ||
4524 | * DS flags set. | ||
4525 | */ | ||
4526 | static int nfs4_check_cl_exchange_flags(u32 flags) | ||
4527 | { | ||
4528 | if (flags & ~EXCHGID4_FLAG_MASK_R) | ||
4529 | goto out_inval; | ||
4530 | if ((flags & EXCHGID4_FLAG_USE_PNFS_MDS) && | ||
4531 | (flags & EXCHGID4_FLAG_USE_NON_PNFS)) | ||
4532 | goto out_inval; | ||
4533 | if (!(flags & (EXCHGID4_FLAG_MASK_PNFS))) | ||
4534 | goto out_inval; | ||
4535 | return NFS_OK; | ||
4536 | out_inval: | ||
4537 | return -NFS4ERR_INVAL; | ||
4538 | } | ||
4539 | |||
4540 | /* | ||
4489 | * nfs4_proc_exchange_id() | 4541 | * nfs4_proc_exchange_id() |
4490 | * | 4542 | * |
4491 | * Since the clientid has expired, all compounds using sessions | 4543 | * Since the clientid has expired, all compounds using sessions |
@@ -4498,7 +4550,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4498 | nfs4_verifier verifier; | 4550 | nfs4_verifier verifier; |
4499 | struct nfs41_exchange_id_args args = { | 4551 | struct nfs41_exchange_id_args args = { |
4500 | .client = clp, | 4552 | .client = clp, |
4501 | .flags = clp->cl_exchange_flags, | 4553 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, |
4502 | }; | 4554 | }; |
4503 | struct nfs41_exchange_id_res res = { | 4555 | struct nfs41_exchange_id_res res = { |
4504 | .client = clp, | 4556 | .client = clp, |
@@ -4515,9 +4567,6 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4515 | dprintk("--> %s\n", __func__); | 4567 | dprintk("--> %s\n", __func__); |
4516 | BUG_ON(clp == NULL); | 4568 | BUG_ON(clp == NULL); |
4517 | 4569 | ||
4518 | /* Remove server-only flags */ | ||
4519 | args.flags &= ~EXCHGID4_FLAG_CONFIRMED_R; | ||
4520 | |||
4521 | p = (u32 *)verifier.data; | 4570 | p = (u32 *)verifier.data; |
4522 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); | 4571 | *p++ = htonl((u32)clp->cl_boot_time.tv_sec); |
4523 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | 4572 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); |
@@ -4543,6 +4592,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4543 | break; | 4592 | break; |
4544 | } | 4593 | } |
4545 | 4594 | ||
4595 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | ||
4546 | dprintk("<-- %s status= %d\n", __func__, status); | 4596 | dprintk("<-- %s status= %d\n", __func__, status); |
4547 | return status; | 4597 | return status; |
4548 | } | 4598 | } |
@@ -4776,17 +4826,17 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
4776 | if (!session) | 4826 | if (!session) |
4777 | return NULL; | 4827 | return NULL; |
4778 | 4828 | ||
4779 | init_completion(&session->complete); | ||
4780 | |||
4781 | tbl = &session->fc_slot_table; | 4829 | tbl = &session->fc_slot_table; |
4782 | tbl->highest_used_slotid = -1; | 4830 | tbl->highest_used_slotid = -1; |
4783 | spin_lock_init(&tbl->slot_tbl_lock); | 4831 | spin_lock_init(&tbl->slot_tbl_lock); |
4784 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | 4832 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); |
4833 | init_completion(&tbl->complete); | ||
4785 | 4834 | ||
4786 | tbl = &session->bc_slot_table; | 4835 | tbl = &session->bc_slot_table; |
4787 | tbl->highest_used_slotid = -1; | 4836 | tbl->highest_used_slotid = -1; |
4788 | spin_lock_init(&tbl->slot_tbl_lock); | 4837 | spin_lock_init(&tbl->slot_tbl_lock); |
4789 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | 4838 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); |
4839 | init_completion(&tbl->complete); | ||
4790 | 4840 | ||
4791 | session->session_state = 1<<NFS4_SESSION_INITING; | 4841 | session->session_state = 1<<NFS4_SESSION_INITING; |
4792 | 4842 | ||
@@ -5280,13 +5330,23 @@ static void | |||
5280 | nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | 5330 | nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) |
5281 | { | 5331 | { |
5282 | struct nfs4_layoutget *lgp = calldata; | 5332 | struct nfs4_layoutget *lgp = calldata; |
5283 | struct inode *ino = lgp->args.inode; | 5333 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
5284 | struct nfs_server *server = NFS_SERVER(ino); | ||
5285 | 5334 | ||
5286 | dprintk("--> %s\n", __func__); | 5335 | dprintk("--> %s\n", __func__); |
5336 | /* Note the is a race here, where a CB_LAYOUTRECALL can come in | ||
5337 | * right now covering the LAYOUTGET we are about to send. | ||
5338 | * However, that is not so catastrophic, and there seems | ||
5339 | * to be no way to prevent it completely. | ||
5340 | */ | ||
5287 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, | 5341 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, |
5288 | &lgp->res.seq_res, 0, task)) | 5342 | &lgp->res.seq_res, 0, task)) |
5289 | return; | 5343 | return; |
5344 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | ||
5345 | NFS_I(lgp->args.inode)->layout, | ||
5346 | lgp->args.ctx->state)) { | ||
5347 | rpc_exit(task, NFS4_OK); | ||
5348 | return; | ||
5349 | } | ||
5290 | rpc_call_start(task); | 5350 | rpc_call_start(task); |
5291 | } | 5351 | } |
5292 | 5352 | ||
@@ -5313,7 +5373,6 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
5313 | return; | 5373 | return; |
5314 | } | 5374 | } |
5315 | } | 5375 | } |
5316 | lgp->status = task->tk_status; | ||
5317 | dprintk("<-- %s\n", __func__); | 5376 | dprintk("<-- %s\n", __func__); |
5318 | } | 5377 | } |
5319 | 5378 | ||
@@ -5322,7 +5381,6 @@ static void nfs4_layoutget_release(void *calldata) | |||
5322 | struct nfs4_layoutget *lgp = calldata; | 5381 | struct nfs4_layoutget *lgp = calldata; |
5323 | 5382 | ||
5324 | dprintk("--> %s\n", __func__); | 5383 | dprintk("--> %s\n", __func__); |
5325 | put_layout_hdr(lgp->args.inode); | ||
5326 | if (lgp->res.layout.buf != NULL) | 5384 | if (lgp->res.layout.buf != NULL) |
5327 | free_page((unsigned long) lgp->res.layout.buf); | 5385 | free_page((unsigned long) lgp->res.layout.buf); |
5328 | put_nfs_open_context(lgp->args.ctx); | 5386 | put_nfs_open_context(lgp->args.ctx); |
@@ -5367,13 +5425,10 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
5367 | if (IS_ERR(task)) | 5425 | if (IS_ERR(task)) |
5368 | return PTR_ERR(task); | 5426 | return PTR_ERR(task); |
5369 | status = nfs4_wait_for_completion_rpc_task(task); | 5427 | status = nfs4_wait_for_completion_rpc_task(task); |
5370 | if (status != 0) | 5428 | if (status == 0) |
5371 | goto out; | 5429 | status = task->tk_status; |
5372 | status = lgp->status; | 5430 | if (status == 0) |
5373 | if (status != 0) | 5431 | status = pnfs_layout_process(lgp); |
5374 | goto out; | ||
5375 | status = pnfs_layout_process(lgp); | ||
5376 | out: | ||
5377 | rpc_put_task(task); | 5432 | rpc_put_task(task); |
5378 | dprintk("<-- %s status=%d\n", __func__, status); | 5433 | dprintk("<-- %s status=%d\n", __func__, status); |
5379 | return status; | 5434 | return status; |
@@ -5504,9 +5559,10 @@ static const struct inode_operations nfs4_file_inode_operations = { | |||
5504 | .permission = nfs_permission, | 5559 | .permission = nfs_permission, |
5505 | .getattr = nfs_getattr, | 5560 | .getattr = nfs_getattr, |
5506 | .setattr = nfs_setattr, | 5561 | .setattr = nfs_setattr, |
5507 | .getxattr = nfs4_getxattr, | 5562 | .getxattr = generic_getxattr, |
5508 | .setxattr = nfs4_setxattr, | 5563 | .setxattr = generic_setxattr, |
5509 | .listxattr = nfs4_listxattr, | 5564 | .listxattr = generic_listxattr, |
5565 | .removexattr = generic_removexattr, | ||
5510 | }; | 5566 | }; |
5511 | 5567 | ||
5512 | const struct nfs_rpc_ops nfs_v4_clientops = { | 5568 | const struct nfs_rpc_ops nfs_v4_clientops = { |
@@ -5551,6 +5607,18 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5551 | .open_context = nfs4_atomic_open, | 5607 | .open_context = nfs4_atomic_open, |
5552 | }; | 5608 | }; |
5553 | 5609 | ||
5610 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | ||
5611 | .prefix = XATTR_NAME_NFSV4_ACL, | ||
5612 | .list = nfs4_xattr_list_nfs4_acl, | ||
5613 | .get = nfs4_xattr_get_nfs4_acl, | ||
5614 | .set = nfs4_xattr_set_nfs4_acl, | ||
5615 | }; | ||
5616 | |||
5617 | const struct xattr_handler *nfs4_xattr_handlers[] = { | ||
5618 | &nfs4_xattr_nfs4_acl_handler, | ||
5619 | NULL | ||
5620 | }; | ||
5621 | |||
5554 | /* | 5622 | /* |
5555 | * Local variables: | 5623 | * Local variables: |
5556 | * c-basic-offset: 8 | 5624 | * c-basic-offset: 8 |