diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:19:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:19:15 -0400 |
commit | bf97293eb878df3792d9de7213bd7b82135aea77 (patch) | |
tree | 16cb367bd78095b9eb8a54c800fcddfcccb618c7 | |
parent | 16d70e15295953b19ecf59e943723a181782b856 (diff) | |
parent | b1b3e136948a2bf4915326acb0d825d7d180753f (diff) |
Merge tag 'nfs-for-3.12-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Highlights include:
- Fix NFSv4 recovery so that it doesn't recover lost locks in cases
such as lease loss due to a network partition, where doing so may
result in data corruption. Add a kernel parameter to control
choice of legacy behaviour or not.
- Performance improvements when 2 processes are writing to the same
file.
- Flush data to disk when an RPCSEC_GSS session timeout is imminent.
- Implement NFSv4.1 SP4_MACH_CRED state protection to prevent other
NFS clients from being able to manipulate our lease and file
locking state.
- Allow sharing of RPCSEC_GSS caches between different rpc clients.
- Fix the broken NFSv4 security auto-negotiation between client and
server.
- Fix rmdir() to wait for outstanding sillyrename unlinks to complete
- Add a tracepoint framework for debugging NFSv4 state recovery
issues.
- Add tracing to the generic NFS layer.
- Add tracing for the SUNRPC socket connection state.
- Clean up the rpc_pipefs mount/umount event management.
- Merge more patches from Chuck in preparation for NFSv4 migration
support"
* tag 'nfs-for-3.12-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (107 commits)
NFSv4: use mach cred for SECINFO_NO_NAME w/ integrity
NFS: nfs_compare_super shouldn't check the auth flavour unless 'sec=' was set
NFSv4: Allow security autonegotiation for submounts
NFSv4: Disallow security negotiation for lookups when 'sec=' is specified
NFSv4: Fix security auto-negotiation
NFS: Clean up nfs_parse_security_flavors()
NFS: Clean up the auth flavour array mess
NFSv4.1 Use MDS auth flavor for data server connection
NFS: Don't check lock owner compatability unless file is locked (part 2)
NFS: Don't check lock owner compatibility in writes unless file is locked
nfs4: Map NFS4ERR_WRONG_CRED to EPERM
nfs4.1: Add SP4_MACH_CRED write and commit support
nfs4.1: Add SP4_MACH_CRED stateid support
nfs4.1: Add SP4_MACH_CRED secinfo support
nfs4.1: Add SP4_MACH_CRED cleanup support
nfs4.1: Add state protection handler
nfs4.1: Minimal SP4_MACH_CRED implementation
SUNRPC: Replace pointer values with task->tk_pid and rpc_clnt->cl_clid
SUNRPC: Add an identifier for struct rpc_clnt
SUNRPC: Ensure rpc_task->tk_pid is available for tracepoints
...
51 files changed, 4504 insertions, 974 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 479eeaf44024..1a036cd972fb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1898,6 +1898,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1898 | will be sent. | 1898 | will be sent. |
1899 | The default is to send the implementation identification | 1899 | The default is to send the implementation identification |
1900 | information. | 1900 | information. |
1901 | |||
1902 | nfs.recover_lost_locks = | ||
1903 | [NFSv4] Attempt to recover locks that were lost due | ||
1904 | to a lease timeout on the server. Please note that | ||
1905 | doing this risks data corruption, since there are | ||
1906 | no guarantees that the file will remain unchanged | ||
1907 | after the locks are lost. | ||
1908 | If you want to enable the kernel legacy behaviour of | ||
1909 | attempting to recover these locks, then set this | ||
1910 | parameter to '1'. | ||
1911 | The default parameter value of '0' causes the kernel | ||
1912 | not to attempt recovery of lost locks. | ||
1901 | 1913 | ||
1902 | nfsd.nfs4_disable_idmapping= | 1914 | nfsd.nfs4_disable_idmapping= |
1903 | [NFSv4] When set to the default of '1', the NFSv4 | 1915 | [NFSv4] When set to the default of '1', the NFSv4 |
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index e0bb048e9576..03192a66c143 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -4,9 +4,10 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_NFS_FS) += nfs.o | 5 | obj-$(CONFIG_NFS_FS) += nfs.o |
6 | 6 | ||
7 | CFLAGS_nfstrace.o += -I$(src) | ||
7 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ | 8 | nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ |
8 | direct.o pagelist.o read.o symlink.o unlink.o \ | 9 | direct.o pagelist.o read.o symlink.o unlink.o \ |
9 | write.o namespace.o mount_clnt.o | 10 | write.o namespace.o mount_clnt.o nfstrace.o |
10 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | 11 | nfs-$(CONFIG_ROOT_NFS) += nfsroot.o |
11 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
12 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
@@ -19,12 +20,14 @@ nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o | |||
19 | nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | 20 | nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o |
20 | 21 | ||
21 | obj-$(CONFIG_NFS_V4) += nfsv4.o | 22 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
23 | CFLAGS_nfs4trace.o += -I$(src) | ||
22 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 24 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
23 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 25 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
24 | nfs4namespace.o nfs4getroot.o nfs4client.o dns_resolve.o | 26 | nfs4namespace.o nfs4getroot.o nfs4client.o nfs4session.o \ |
27 | dns_resolve.o nfs4trace.o | ||
25 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o | 28 | nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o |
26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 29 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o | 30 | nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o |
28 | 31 | ||
29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o | 32 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o |
30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o | 33 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index e6ebc4c38c81..ae2e87b95453 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "internal.h" | 15 | #include "internal.h" |
16 | #include "pnfs.h" | 16 | #include "pnfs.h" |
17 | #include "nfs4session.h" | 17 | #include "nfs4session.h" |
18 | #include "nfs4trace.h" | ||
18 | 19 | ||
19 | #ifdef NFS_DEBUG | 20 | #ifdef NFS_DEBUG |
20 | #define NFSDBG_FACILITY NFSDBG_CALLBACK | 21 | #define NFSDBG_FACILITY NFSDBG_CALLBACK |
@@ -93,6 +94,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy, | |||
93 | default: | 94 | default: |
94 | res = htonl(NFS4ERR_RESOURCE); | 95 | res = htonl(NFS4ERR_RESOURCE); |
95 | } | 96 | } |
97 | trace_nfs4_recall_delegation(inode, -ntohl(res)); | ||
96 | iput(inode); | 98 | iput(inode); |
97 | out: | 99 | out: |
98 | dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); | 100 | dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); |
@@ -301,14 +303,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args) | |||
301 | { | 303 | { |
302 | struct nfs4_slot *slot; | 304 | struct nfs4_slot *slot; |
303 | 305 | ||
304 | dprintk("%s enter. slotid %d seqid %d\n", | 306 | dprintk("%s enter. slotid %u seqid %u\n", |
305 | __func__, args->csa_slotid, args->csa_sequenceid); | 307 | __func__, args->csa_slotid, args->csa_sequenceid); |
306 | 308 | ||
307 | if (args->csa_slotid >= NFS41_BC_MAX_CALLBACKS) | 309 | if (args->csa_slotid >= NFS41_BC_MAX_CALLBACKS) |
308 | return htonl(NFS4ERR_BADSLOT); | 310 | return htonl(NFS4ERR_BADSLOT); |
309 | 311 | ||
310 | slot = tbl->slots + args->csa_slotid; | 312 | slot = tbl->slots + args->csa_slotid; |
311 | dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr); | 313 | dprintk("%s slot table seqid: %u\n", __func__, slot->seq_nr); |
312 | 314 | ||
313 | /* Normal */ | 315 | /* Normal */ |
314 | if (likely(args->csa_sequenceid == slot->seq_nr + 1)) { | 316 | if (likely(args->csa_sequenceid == slot->seq_nr + 1)) { |
@@ -318,7 +320,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args) | |||
318 | 320 | ||
319 | /* Replay */ | 321 | /* Replay */ |
320 | if (args->csa_sequenceid == slot->seq_nr) { | 322 | if (args->csa_sequenceid == slot->seq_nr) { |
321 | dprintk("%s seqid %d is a replay\n", | 323 | dprintk("%s seqid %u is a replay\n", |
322 | __func__, args->csa_sequenceid); | 324 | __func__, args->csa_sequenceid); |
323 | /* Signal process_op to set this error on next op */ | 325 | /* Signal process_op to set this error on next op */ |
324 | if (args->csa_cachethis == 0) | 326 | if (args->csa_cachethis == 0) |
@@ -462,6 +464,7 @@ out: | |||
462 | } else | 464 | } else |
463 | res->csr_status = status; | 465 | res->csr_status = status; |
464 | 466 | ||
467 | trace_nfs4_cb_sequence(args, res, status); | ||
465 | dprintk("%s: exit with status = %d res->csr_status %d\n", __func__, | 468 | dprintk("%s: exit with status = %d res->csr_status %d\n", __func__, |
466 | ntohl(status), ntohl(res->csr_status)); | 469 | ntohl(status), ntohl(res->csr_status)); |
467 | return status; | 470 | return status; |
@@ -518,7 +521,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, | |||
518 | if (!cps->clp) /* set in cb_sequence */ | 521 | if (!cps->clp) /* set in cb_sequence */ |
519 | goto out; | 522 | goto out; |
520 | 523 | ||
521 | dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %d\n", | 524 | dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %u\n", |
522 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), | 525 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), |
523 | args->crsa_target_highest_slotid); | 526 | args->crsa_target_highest_slotid); |
524 | 527 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 340b1eff0267..2dceee4db076 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -501,8 +501,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, | |||
501 | &nn->nfs_client_list); | 501 | &nn->nfs_client_list); |
502 | spin_unlock(&nn->nfs_client_lock); | 502 | spin_unlock(&nn->nfs_client_lock); |
503 | new->cl_flags = cl_init->init_flags; | 503 | new->cl_flags = cl_init->init_flags; |
504 | return rpc_ops->init_client(new, timeparms, ip_addr, | 504 | return rpc_ops->init_client(new, timeparms, ip_addr); |
505 | authflavour); | ||
506 | } | 505 | } |
507 | 506 | ||
508 | spin_unlock(&nn->nfs_client_lock); | 507 | spin_unlock(&nn->nfs_client_lock); |
@@ -694,13 +693,12 @@ EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient); | |||
694 | * @clp: nfs_client to initialise | 693 | * @clp: nfs_client to initialise |
695 | * @timeparms: timeout parameters for underlying RPC transport | 694 | * @timeparms: timeout parameters for underlying RPC transport |
696 | * @ip_addr: IP presentation address (not used) | 695 | * @ip_addr: IP presentation address (not used) |
697 | * @authflavor: authentication flavor for underlying RPC transport | ||
698 | * | 696 | * |
699 | * Returns pointer to an NFS client, or an ERR_PTR value. | 697 | * Returns pointer to an NFS client, or an ERR_PTR value. |
700 | */ | 698 | */ |
701 | struct nfs_client *nfs_init_client(struct nfs_client *clp, | 699 | struct nfs_client *nfs_init_client(struct nfs_client *clp, |
702 | const struct rpc_timeout *timeparms, | 700 | const struct rpc_timeout *timeparms, |
703 | const char *ip_addr, rpc_authflavor_t authflavour) | 701 | const char *ip_addr) |
704 | { | 702 | { |
705 | int error; | 703 | int error; |
706 | 704 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 7ec4814e298d..ef792f29f831 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "nfs4_fs.h" | 20 | #include "nfs4_fs.h" |
21 | #include "delegation.h" | 21 | #include "delegation.h" |
22 | #include "internal.h" | 22 | #include "internal.h" |
23 | #include "nfs4trace.h" | ||
23 | 24 | ||
24 | static void nfs_free_delegation(struct nfs_delegation *delegation) | 25 | static void nfs_free_delegation(struct nfs_delegation *delegation) |
25 | { | 26 | { |
@@ -160,6 +161,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, | |||
160 | spin_unlock(&delegation->lock); | 161 | spin_unlock(&delegation->lock); |
161 | put_rpccred(oldcred); | 162 | put_rpccred(oldcred); |
162 | rcu_read_unlock(); | 163 | rcu_read_unlock(); |
164 | trace_nfs4_reclaim_delegation(inode, res->delegation_type); | ||
163 | } else { | 165 | } else { |
164 | /* We appear to have raced with a delegation return. */ | 166 | /* We appear to have raced with a delegation return. */ |
165 | spin_unlock(&delegation->lock); | 167 | spin_unlock(&delegation->lock); |
@@ -344,6 +346,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
344 | spin_lock(&inode->i_lock); | 346 | spin_lock(&inode->i_lock); |
345 | nfsi->cache_validity |= NFS_INO_REVAL_FORCED; | 347 | nfsi->cache_validity |= NFS_INO_REVAL_FORCED; |
346 | spin_unlock(&inode->i_lock); | 348 | spin_unlock(&inode->i_lock); |
349 | trace_nfs4_set_delegation(inode, res->delegation_type); | ||
347 | 350 | ||
348 | out: | 351 | out: |
349 | spin_unlock(&clp->cl_lock); | 352 | spin_unlock(&clp->cl_lock); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7468735d299e..e79bc6ce828e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include "internal.h" | 43 | #include "internal.h" |
44 | #include "fscache.h" | 44 | #include "fscache.h" |
45 | 45 | ||
46 | #include "nfstrace.h" | ||
47 | |||
46 | /* #define NFS_DEBUG_VERBOSE 1 */ | 48 | /* #define NFS_DEBUG_VERBOSE 1 */ |
47 | 49 | ||
48 | static int nfs_opendir(struct inode *, struct file *); | 50 | static int nfs_opendir(struct inode *, struct file *); |
@@ -1100,7 +1102,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1100 | if (IS_ERR(label)) | 1102 | if (IS_ERR(label)) |
1101 | goto out_error; | 1103 | goto out_error; |
1102 | 1104 | ||
1105 | trace_nfs_lookup_revalidate_enter(dir, dentry, flags); | ||
1103 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1106 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1107 | trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); | ||
1104 | if (error) | 1108 | if (error) |
1105 | goto out_bad; | 1109 | goto out_bad; |
1106 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1110 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -1312,6 +1316,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1312 | 1316 | ||
1313 | parent = dentry->d_parent; | 1317 | parent = dentry->d_parent; |
1314 | /* Protect against concurrent sillydeletes */ | 1318 | /* Protect against concurrent sillydeletes */ |
1319 | trace_nfs_lookup_enter(dir, dentry, flags); | ||
1315 | nfs_block_sillyrename(parent); | 1320 | nfs_block_sillyrename(parent); |
1316 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | 1321 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1317 | if (error == -ENOENT) | 1322 | if (error == -ENOENT) |
@@ -1338,6 +1343,7 @@ no_entry: | |||
1338 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1343 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1339 | out_unblock_sillyrename: | 1344 | out_unblock_sillyrename: |
1340 | nfs_unblock_sillyrename(parent); | 1345 | nfs_unblock_sillyrename(parent); |
1346 | trace_nfs_lookup_exit(dir, dentry, flags, error); | ||
1341 | nfs4_label_free(label); | 1347 | nfs4_label_free(label); |
1342 | out: | 1348 | out: |
1343 | nfs_free_fattr(fattr); | 1349 | nfs_free_fattr(fattr); |
@@ -1392,7 +1398,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
1392 | nfs_file_set_open_context(file, ctx); | 1398 | nfs_file_set_open_context(file, ctx); |
1393 | 1399 | ||
1394 | out: | 1400 | out: |
1395 | put_nfs_open_context(ctx); | ||
1396 | return err; | 1401 | return err; |
1397 | } | 1402 | } |
1398 | 1403 | ||
@@ -1404,6 +1409,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1404 | struct dentry *res; | 1409 | struct dentry *res; |
1405 | struct iattr attr = { .ia_valid = ATTR_OPEN }; | 1410 | struct iattr attr = { .ia_valid = ATTR_OPEN }; |
1406 | struct inode *inode; | 1411 | struct inode *inode; |
1412 | unsigned int lookup_flags = 0; | ||
1407 | int err; | 1413 | int err; |
1408 | 1414 | ||
1409 | /* Expect a negative dentry */ | 1415 | /* Expect a negative dentry */ |
@@ -1412,6 +1418,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1412 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", | 1418 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", |
1413 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1419 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1414 | 1420 | ||
1421 | err = nfs_check_flags(open_flags); | ||
1422 | if (err) | ||
1423 | return err; | ||
1424 | |||
1415 | /* NFS only supports OPEN on regular files */ | 1425 | /* NFS only supports OPEN on regular files */ |
1416 | if ((open_flags & O_DIRECTORY)) { | 1426 | if ((open_flags & O_DIRECTORY)) { |
1417 | if (!d_unhashed(dentry)) { | 1427 | if (!d_unhashed(dentry)) { |
@@ -1422,6 +1432,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1422 | */ | 1432 | */ |
1423 | return -ENOENT; | 1433 | return -ENOENT; |
1424 | } | 1434 | } |
1435 | lookup_flags = LOOKUP_OPEN|LOOKUP_DIRECTORY; | ||
1425 | goto no_open; | 1436 | goto no_open; |
1426 | } | 1437 | } |
1427 | 1438 | ||
@@ -1442,12 +1453,14 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1442 | if (IS_ERR(ctx)) | 1453 | if (IS_ERR(ctx)) |
1443 | goto out; | 1454 | goto out; |
1444 | 1455 | ||
1456 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); | ||
1445 | nfs_block_sillyrename(dentry->d_parent); | 1457 | nfs_block_sillyrename(dentry->d_parent); |
1446 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1458 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1447 | nfs_unblock_sillyrename(dentry->d_parent); | 1459 | nfs_unblock_sillyrename(dentry->d_parent); |
1448 | if (IS_ERR(inode)) { | 1460 | if (IS_ERR(inode)) { |
1449 | put_nfs_open_context(ctx); | ||
1450 | err = PTR_ERR(inode); | 1461 | err = PTR_ERR(inode); |
1462 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | ||
1463 | put_nfs_open_context(ctx); | ||
1451 | switch (err) { | 1464 | switch (err) { |
1452 | case -ENOENT: | 1465 | case -ENOENT: |
1453 | d_drop(dentry); | 1466 | d_drop(dentry); |
@@ -1468,11 +1481,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1468 | } | 1481 | } |
1469 | 1482 | ||
1470 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); | 1483 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
1484 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | ||
1485 | put_nfs_open_context(ctx); | ||
1471 | out: | 1486 | out: |
1472 | return err; | 1487 | return err; |
1473 | 1488 | ||
1474 | no_open: | 1489 | no_open: |
1475 | res = nfs_lookup(dir, dentry, 0); | 1490 | res = nfs_lookup(dir, dentry, lookup_flags); |
1476 | err = PTR_ERR(res); | 1491 | err = PTR_ERR(res); |
1477 | if (IS_ERR(res)) | 1492 | if (IS_ERR(res)) |
1478 | goto out; | 1493 | goto out; |
@@ -1596,7 +1611,9 @@ int nfs_create(struct inode *dir, struct dentry *dentry, | |||
1596 | attr.ia_mode = mode; | 1611 | attr.ia_mode = mode; |
1597 | attr.ia_valid = ATTR_MODE; | 1612 | attr.ia_valid = ATTR_MODE; |
1598 | 1613 | ||
1614 | trace_nfs_create_enter(dir, dentry, open_flags); | ||
1599 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); | 1615 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); |
1616 | trace_nfs_create_exit(dir, dentry, open_flags, error); | ||
1600 | if (error != 0) | 1617 | if (error != 0) |
1601 | goto out_err; | 1618 | goto out_err; |
1602 | return 0; | 1619 | return 0; |
@@ -1624,7 +1641,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) | |||
1624 | attr.ia_mode = mode; | 1641 | attr.ia_mode = mode; |
1625 | attr.ia_valid = ATTR_MODE; | 1642 | attr.ia_valid = ATTR_MODE; |
1626 | 1643 | ||
1644 | trace_nfs_mknod_enter(dir, dentry); | ||
1627 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); | 1645 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); |
1646 | trace_nfs_mknod_exit(dir, dentry, status); | ||
1628 | if (status != 0) | 1647 | if (status != 0) |
1629 | goto out_err; | 1648 | goto out_err; |
1630 | return 0; | 1649 | return 0; |
@@ -1648,7 +1667,9 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1648 | attr.ia_valid = ATTR_MODE; | 1667 | attr.ia_valid = ATTR_MODE; |
1649 | attr.ia_mode = mode | S_IFDIR; | 1668 | attr.ia_mode = mode | S_IFDIR; |
1650 | 1669 | ||
1670 | trace_nfs_mkdir_enter(dir, dentry); | ||
1651 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); | 1671 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); |
1672 | trace_nfs_mkdir_exit(dir, dentry, error); | ||
1652 | if (error != 0) | 1673 | if (error != 0) |
1653 | goto out_err; | 1674 | goto out_err; |
1654 | return 0; | 1675 | return 0; |
@@ -1671,12 +1692,21 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1671 | dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", | 1692 | dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n", |
1672 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1693 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1673 | 1694 | ||
1674 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | 1695 | trace_nfs_rmdir_enter(dir, dentry); |
1675 | /* Ensure the VFS deletes this inode */ | 1696 | if (dentry->d_inode) { |
1676 | if (error == 0 && dentry->d_inode != NULL) | 1697 | nfs_wait_on_sillyrename(dentry); |
1677 | clear_nlink(dentry->d_inode); | 1698 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); |
1678 | else if (error == -ENOENT) | 1699 | /* Ensure the VFS deletes this inode */ |
1679 | nfs_dentry_handle_enoent(dentry); | 1700 | switch (error) { |
1701 | case 0: | ||
1702 | clear_nlink(dentry->d_inode); | ||
1703 | break; | ||
1704 | case -ENOENT: | ||
1705 | nfs_dentry_handle_enoent(dentry); | ||
1706 | } | ||
1707 | } else | ||
1708 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | ||
1709 | trace_nfs_rmdir_exit(dir, dentry, error); | ||
1680 | 1710 | ||
1681 | return error; | 1711 | return error; |
1682 | } | 1712 | } |
@@ -1704,6 +1734,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1704 | goto out; | 1734 | goto out; |
1705 | } | 1735 | } |
1706 | 1736 | ||
1737 | trace_nfs_remove_enter(dir, dentry); | ||
1707 | if (inode != NULL) { | 1738 | if (inode != NULL) { |
1708 | NFS_PROTO(inode)->return_delegation(inode); | 1739 | NFS_PROTO(inode)->return_delegation(inode); |
1709 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1740 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
@@ -1713,6 +1744,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1713 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1744 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1714 | if (error == -ENOENT) | 1745 | if (error == -ENOENT) |
1715 | nfs_dentry_handle_enoent(dentry); | 1746 | nfs_dentry_handle_enoent(dentry); |
1747 | trace_nfs_remove_exit(dir, dentry, error); | ||
1716 | out: | 1748 | out: |
1717 | return error; | 1749 | return error; |
1718 | } | 1750 | } |
@@ -1730,13 +1762,14 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1730 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, | 1762 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, |
1731 | dir->i_ino, dentry->d_name.name); | 1763 | dir->i_ino, dentry->d_name.name); |
1732 | 1764 | ||
1765 | trace_nfs_unlink_enter(dir, dentry); | ||
1733 | spin_lock(&dentry->d_lock); | 1766 | spin_lock(&dentry->d_lock); |
1734 | if (d_count(dentry) > 1) { | 1767 | if (d_count(dentry) > 1) { |
1735 | spin_unlock(&dentry->d_lock); | 1768 | spin_unlock(&dentry->d_lock); |
1736 | /* Start asynchronous writeout of the inode */ | 1769 | /* Start asynchronous writeout of the inode */ |
1737 | write_inode_now(dentry->d_inode, 0); | 1770 | write_inode_now(dentry->d_inode, 0); |
1738 | error = nfs_sillyrename(dir, dentry); | 1771 | error = nfs_sillyrename(dir, dentry); |
1739 | return error; | 1772 | goto out; |
1740 | } | 1773 | } |
1741 | if (!d_unhashed(dentry)) { | 1774 | if (!d_unhashed(dentry)) { |
1742 | __d_drop(dentry); | 1775 | __d_drop(dentry); |
@@ -1748,6 +1781,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1748 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1781 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1749 | } else if (need_rehash) | 1782 | } else if (need_rehash) |
1750 | d_rehash(dentry); | 1783 | d_rehash(dentry); |
1784 | out: | ||
1785 | trace_nfs_unlink_exit(dir, dentry, error); | ||
1751 | return error; | 1786 | return error; |
1752 | } | 1787 | } |
1753 | EXPORT_SYMBOL_GPL(nfs_unlink); | 1788 | EXPORT_SYMBOL_GPL(nfs_unlink); |
@@ -1794,7 +1829,9 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1794 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | 1829 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); |
1795 | kunmap_atomic(kaddr); | 1830 | kunmap_atomic(kaddr); |
1796 | 1831 | ||
1832 | trace_nfs_symlink_enter(dir, dentry); | ||
1797 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | 1833 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
1834 | trace_nfs_symlink_exit(dir, dentry, error); | ||
1798 | if (error != 0) { | 1835 | if (error != 0) { |
1799 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", | 1836 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", |
1800 | dir->i_sb->s_id, dir->i_ino, | 1837 | dir->i_sb->s_id, dir->i_ino, |
@@ -1829,6 +1866,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1829 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1866 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1830 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1867 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1831 | 1868 | ||
1869 | trace_nfs_link_enter(inode, dir, dentry); | ||
1832 | NFS_PROTO(inode)->return_delegation(inode); | 1870 | NFS_PROTO(inode)->return_delegation(inode); |
1833 | 1871 | ||
1834 | d_drop(dentry); | 1872 | d_drop(dentry); |
@@ -1837,6 +1875,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1837 | ihold(inode); | 1875 | ihold(inode); |
1838 | d_add(dentry, inode); | 1876 | d_add(dentry, inode); |
1839 | } | 1877 | } |
1878 | trace_nfs_link_exit(inode, dir, dentry, error); | ||
1840 | return error; | 1879 | return error; |
1841 | } | 1880 | } |
1842 | EXPORT_SYMBOL_GPL(nfs_link); | 1881 | EXPORT_SYMBOL_GPL(nfs_link); |
@@ -1878,6 +1917,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1878 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1917 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1879 | d_count(new_dentry)); | 1918 | d_count(new_dentry)); |
1880 | 1919 | ||
1920 | trace_nfs_rename_enter(old_dir, old_dentry, new_dir, new_dentry); | ||
1881 | /* | 1921 | /* |
1882 | * For non-directories, check whether the target is busy and if so, | 1922 | * For non-directories, check whether the target is busy and if so, |
1883 | * make a copy of the dentry and then do a silly-rename. If the | 1923 | * make a copy of the dentry and then do a silly-rename. If the |
@@ -1924,6 +1964,8 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1924 | out: | 1964 | out: |
1925 | if (rehash) | 1965 | if (rehash) |
1926 | d_rehash(rehash); | 1966 | d_rehash(rehash); |
1967 | trace_nfs_rename_exit(old_dir, old_dentry, | ||
1968 | new_dir, new_dentry, error); | ||
1927 | if (!error) { | 1969 | if (!error) { |
1928 | if (new_inode != NULL) | 1970 | if (new_inode != NULL) |
1929 | nfs_drop_nlink(new_inode); | 1971 | nfs_drop_nlink(new_inode); |
@@ -2173,9 +2215,11 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
2173 | struct nfs_access_entry cache; | 2215 | struct nfs_access_entry cache; |
2174 | int status; | 2216 | int status; |
2175 | 2217 | ||
2218 | trace_nfs_access_enter(inode); | ||
2219 | |||
2176 | status = nfs_access_get_cached(inode, cred, &cache); | 2220 | status = nfs_access_get_cached(inode, cred, &cache); |
2177 | if (status == 0) | 2221 | if (status == 0) |
2178 | goto out; | 2222 | goto out_cached; |
2179 | 2223 | ||
2180 | /* Be clever: ask server to check for all possible rights */ | 2224 | /* Be clever: ask server to check for all possible rights */ |
2181 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; | 2225 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; |
@@ -2188,13 +2232,15 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) | |||
2188 | if (!S_ISDIR(inode->i_mode)) | 2232 | if (!S_ISDIR(inode->i_mode)) |
2189 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | 2233 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
2190 | } | 2234 | } |
2191 | return status; | 2235 | goto out; |
2192 | } | 2236 | } |
2193 | nfs_access_add_cache(inode, &cache); | 2237 | nfs_access_add_cache(inode, &cache); |
2238 | out_cached: | ||
2239 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) | ||
2240 | status = -EACCES; | ||
2194 | out: | 2241 | out: |
2195 | if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 2242 | trace_nfs_access_exit(inode, status); |
2196 | return 0; | 2243 | return status; |
2197 | return -EACCES; | ||
2198 | } | 2244 | } |
2199 | 2245 | ||
2200 | static int nfs_open_permission_mask(int openflags) | 2246 | static int nfs_open_permission_mask(int openflags) |
@@ -2240,11 +2286,6 @@ int nfs_permission(struct inode *inode, int mask) | |||
2240 | case S_IFLNK: | 2286 | case S_IFLNK: |
2241 | goto out; | 2287 | goto out; |
2242 | case S_IFREG: | 2288 | case S_IFREG: |
2243 | /* NFSv4 has atomic_open... */ | ||
2244 | if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN) | ||
2245 | && (mask & MAY_OPEN) | ||
2246 | && !(mask & MAY_EXEC)) | ||
2247 | goto out; | ||
2248 | break; | 2289 | break; |
2249 | case S_IFDIR: | 2290 | case S_IFDIR: |
2250 | /* | 2291 | /* |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 94e94bd11aae..1e6bfdbc1aff 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include "iostat.h" | 37 | #include "iostat.h" |
38 | #include "fscache.h" | 38 | #include "fscache.h" |
39 | 39 | ||
40 | #include "nfstrace.h" | ||
41 | |||
40 | #define NFSDBG_FACILITY NFSDBG_FILE | 42 | #define NFSDBG_FACILITY NFSDBG_FILE |
41 | 43 | ||
42 | static const struct vm_operations_struct nfs_file_vm_ops; | 44 | static const struct vm_operations_struct nfs_file_vm_ops; |
@@ -294,6 +296,8 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
294 | int ret; | 296 | int ret; |
295 | struct inode *inode = file_inode(file); | 297 | struct inode *inode = file_inode(file); |
296 | 298 | ||
299 | trace_nfs_fsync_enter(inode); | ||
300 | |||
297 | do { | 301 | do { |
298 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 302 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
299 | if (ret != 0) | 303 | if (ret != 0) |
@@ -310,6 +314,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
310 | end = LLONG_MAX; | 314 | end = LLONG_MAX; |
311 | } while (ret == -EAGAIN); | 315 | } while (ret == -EAGAIN); |
312 | 316 | ||
317 | trace_nfs_fsync_exit(inode, ret); | ||
313 | return ret; | 318 | return ret; |
314 | } | 319 | } |
315 | 320 | ||
@@ -406,6 +411,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
406 | struct page *page, void *fsdata) | 411 | struct page *page, void *fsdata) |
407 | { | 412 | { |
408 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | 413 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); |
414 | struct nfs_open_context *ctx = nfs_file_open_context(file); | ||
409 | int status; | 415 | int status; |
410 | 416 | ||
411 | dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", | 417 | dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", |
@@ -441,6 +447,13 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
441 | if (status < 0) | 447 | if (status < 0) |
442 | return status; | 448 | return status; |
443 | NFS_I(mapping->host)->write_io += copied; | 449 | NFS_I(mapping->host)->write_io += copied; |
450 | |||
451 | if (nfs_ctx_key_to_expire(ctx)) { | ||
452 | status = nfs_wb_all(mapping->host); | ||
453 | if (status < 0) | ||
454 | return status; | ||
455 | } | ||
456 | |||
444 | return copied; | 457 | return copied; |
445 | } | 458 | } |
446 | 459 | ||
@@ -637,7 +650,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) | |||
637 | if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) | 650 | if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) |
638 | return 1; | 651 | return 1; |
639 | ctx = nfs_file_open_context(filp); | 652 | ctx = nfs_file_open_context(filp); |
640 | if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) | 653 | if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags) || |
654 | nfs_ctx_key_to_expire(ctx)) | ||
641 | return 1; | 655 | return 1; |
642 | return 0; | 656 | return 0; |
643 | } | 657 | } |
@@ -651,6 +665,10 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
651 | ssize_t result; | 665 | ssize_t result; |
652 | size_t count = iov_length(iov, nr_segs); | 666 | size_t count = iov_length(iov, nr_segs); |
653 | 667 | ||
668 | result = nfs_key_timeout_notify(iocb->ki_filp, inode); | ||
669 | if (result) | ||
670 | return result; | ||
671 | |||
654 | if (iocb->ki_filp->f_flags & O_DIRECT) | 672 | if (iocb->ki_filp->f_flags & O_DIRECT) |
655 | return nfs_file_direct_write(iocb, iov, nr_segs, pos, true); | 673 | return nfs_file_direct_write(iocb, iov, nr_segs, pos, true); |
656 | 674 | ||
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index c2c4163d5683..567983d2c0eb 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -49,6 +49,7 @@ | |||
49 | 49 | ||
50 | #include "internal.h" | 50 | #include "internal.h" |
51 | #include "netns.h" | 51 | #include "netns.h" |
52 | #include "nfs4trace.h" | ||
52 | 53 | ||
53 | #define NFS_UINT_MAXLEN 11 | 54 | #define NFS_UINT_MAXLEN 11 |
54 | 55 | ||
@@ -63,6 +64,7 @@ struct idmap_legacy_upcalldata { | |||
63 | }; | 64 | }; |
64 | 65 | ||
65 | struct idmap { | 66 | struct idmap { |
67 | struct rpc_pipe_dir_object idmap_pdo; | ||
66 | struct rpc_pipe *idmap_pipe; | 68 | struct rpc_pipe *idmap_pipe; |
67 | struct idmap_legacy_upcalldata *idmap_upcall_data; | 69 | struct idmap_legacy_upcalldata *idmap_upcall_data; |
68 | struct mutex idmap_mutex; | 70 | struct mutex idmap_mutex; |
@@ -310,7 +312,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | |||
310 | if (ret < 0) | 312 | if (ret < 0) |
311 | goto out_up; | 313 | goto out_up; |
312 | 314 | ||
313 | payload = rcu_dereference(rkey->payload.data); | 315 | payload = rcu_dereference(rkey->payload.rcudata); |
314 | if (IS_ERR_OR_NULL(payload)) { | 316 | if (IS_ERR_OR_NULL(payload)) { |
315 | ret = PTR_ERR(payload); | 317 | ret = PTR_ERR(payload); |
316 | goto out_up; | 318 | goto out_up; |
@@ -401,16 +403,23 @@ static struct key_type key_type_id_resolver_legacy = { | |||
401 | .request_key = nfs_idmap_legacy_upcall, | 403 | .request_key = nfs_idmap_legacy_upcall, |
402 | }; | 404 | }; |
403 | 405 | ||
404 | static void __nfs_idmap_unregister(struct rpc_pipe *pipe) | 406 | static void nfs_idmap_pipe_destroy(struct dentry *dir, |
407 | struct rpc_pipe_dir_object *pdo) | ||
405 | { | 408 | { |
406 | if (pipe->dentry) | 409 | struct idmap *idmap = pdo->pdo_data; |
410 | struct rpc_pipe *pipe = idmap->idmap_pipe; | ||
411 | |||
412 | if (pipe->dentry) { | ||
407 | rpc_unlink(pipe->dentry); | 413 | rpc_unlink(pipe->dentry); |
414 | pipe->dentry = NULL; | ||
415 | } | ||
408 | } | 416 | } |
409 | 417 | ||
410 | static int __nfs_idmap_register(struct dentry *dir, | 418 | static int nfs_idmap_pipe_create(struct dentry *dir, |
411 | struct idmap *idmap, | 419 | struct rpc_pipe_dir_object *pdo) |
412 | struct rpc_pipe *pipe) | ||
413 | { | 420 | { |
421 | struct idmap *idmap = pdo->pdo_data; | ||
422 | struct rpc_pipe *pipe = idmap->idmap_pipe; | ||
414 | struct dentry *dentry; | 423 | struct dentry *dentry; |
415 | 424 | ||
416 | dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe); | 425 | dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe); |
@@ -420,36 +429,10 @@ static int __nfs_idmap_register(struct dentry *dir, | |||
420 | return 0; | 429 | return 0; |
421 | } | 430 | } |
422 | 431 | ||
423 | static void nfs_idmap_unregister(struct nfs_client *clp, | 432 | static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = { |
424 | struct rpc_pipe *pipe) | 433 | .create = nfs_idmap_pipe_create, |
425 | { | 434 | .destroy = nfs_idmap_pipe_destroy, |
426 | struct net *net = clp->cl_net; | 435 | }; |
427 | struct super_block *pipefs_sb; | ||
428 | |||
429 | pipefs_sb = rpc_get_sb_net(net); | ||
430 | if (pipefs_sb) { | ||
431 | __nfs_idmap_unregister(pipe); | ||
432 | rpc_put_sb_net(net); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | static int nfs_idmap_register(struct nfs_client *clp, | ||
437 | struct idmap *idmap, | ||
438 | struct rpc_pipe *pipe) | ||
439 | { | ||
440 | struct net *net = clp->cl_net; | ||
441 | struct super_block *pipefs_sb; | ||
442 | int err = 0; | ||
443 | |||
444 | pipefs_sb = rpc_get_sb_net(net); | ||
445 | if (pipefs_sb) { | ||
446 | if (clp->cl_rpcclient->cl_dentry) | ||
447 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, | ||
448 | idmap, pipe); | ||
449 | rpc_put_sb_net(net); | ||
450 | } | ||
451 | return err; | ||
452 | } | ||
453 | 436 | ||
454 | int | 437 | int |
455 | nfs_idmap_new(struct nfs_client *clp) | 438 | nfs_idmap_new(struct nfs_client *clp) |
@@ -462,23 +445,31 @@ nfs_idmap_new(struct nfs_client *clp) | |||
462 | if (idmap == NULL) | 445 | if (idmap == NULL) |
463 | return -ENOMEM; | 446 | return -ENOMEM; |
464 | 447 | ||
448 | rpc_init_pipe_dir_object(&idmap->idmap_pdo, | ||
449 | &nfs_idmap_pipe_dir_object_ops, | ||
450 | idmap); | ||
451 | |||
465 | pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0); | 452 | pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0); |
466 | if (IS_ERR(pipe)) { | 453 | if (IS_ERR(pipe)) { |
467 | error = PTR_ERR(pipe); | 454 | error = PTR_ERR(pipe); |
468 | kfree(idmap); | 455 | goto err; |
469 | return error; | ||
470 | } | ||
471 | error = nfs_idmap_register(clp, idmap, pipe); | ||
472 | if (error) { | ||
473 | rpc_destroy_pipe_data(pipe); | ||
474 | kfree(idmap); | ||
475 | return error; | ||
476 | } | 456 | } |
477 | idmap->idmap_pipe = pipe; | 457 | idmap->idmap_pipe = pipe; |
478 | mutex_init(&idmap->idmap_mutex); | 458 | mutex_init(&idmap->idmap_mutex); |
479 | 459 | ||
460 | error = rpc_add_pipe_dir_object(clp->cl_net, | ||
461 | &clp->cl_rpcclient->cl_pipedir_objects, | ||
462 | &idmap->idmap_pdo); | ||
463 | if (error) | ||
464 | goto err_destroy_pipe; | ||
465 | |||
480 | clp->cl_idmap = idmap; | 466 | clp->cl_idmap = idmap; |
481 | return 0; | 467 | return 0; |
468 | err_destroy_pipe: | ||
469 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
470 | err: | ||
471 | kfree(idmap); | ||
472 | return error; | ||
482 | } | 473 | } |
483 | 474 | ||
484 | void | 475 | void |
@@ -488,130 +479,26 @@ nfs_idmap_delete(struct nfs_client *clp) | |||
488 | 479 | ||
489 | if (!idmap) | 480 | if (!idmap) |
490 | return; | 481 | return; |
491 | nfs_idmap_unregister(clp, idmap->idmap_pipe); | ||
492 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
493 | clp->cl_idmap = NULL; | 482 | clp->cl_idmap = NULL; |
483 | rpc_remove_pipe_dir_object(clp->cl_net, | ||
484 | &clp->cl_rpcclient->cl_pipedir_objects, | ||
485 | &idmap->idmap_pdo); | ||
486 | rpc_destroy_pipe_data(idmap->idmap_pipe); | ||
494 | kfree(idmap); | 487 | kfree(idmap); |
495 | } | 488 | } |
496 | 489 | ||
497 | static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event, | ||
498 | struct super_block *sb) | ||
499 | { | ||
500 | int err = 0; | ||
501 | |||
502 | switch (event) { | ||
503 | case RPC_PIPEFS_MOUNT: | ||
504 | err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, | ||
505 | clp->cl_idmap, | ||
506 | clp->cl_idmap->idmap_pipe); | ||
507 | break; | ||
508 | case RPC_PIPEFS_UMOUNT: | ||
509 | if (clp->cl_idmap->idmap_pipe) { | ||
510 | struct dentry *parent; | ||
511 | |||
512 | parent = clp->cl_idmap->idmap_pipe->dentry->d_parent; | ||
513 | __nfs_idmap_unregister(clp->cl_idmap->idmap_pipe); | ||
514 | /* | ||
515 | * Note: This is a dirty hack. SUNRPC hook has been | ||
516 | * called already but simple_rmdir() call for the | ||
517 | * directory returned with error because of idmap pipe | ||
518 | * inside. Thus now we have to remove this directory | ||
519 | * here. | ||
520 | */ | ||
521 | if (rpc_rmdir(parent)) | ||
522 | printk(KERN_ERR "NFS: %s: failed to remove " | ||
523 | "clnt dir!\n", __func__); | ||
524 | } | ||
525 | break; | ||
526 | default: | ||
527 | printk(KERN_ERR "NFS: %s: unknown event: %ld\n", __func__, | ||
528 | event); | ||
529 | return -ENOTSUPP; | ||
530 | } | ||
531 | return err; | ||
532 | } | ||
533 | |||
534 | static struct nfs_client *nfs_get_client_for_event(struct net *net, int event) | ||
535 | { | ||
536 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
537 | struct dentry *cl_dentry; | ||
538 | struct nfs_client *clp; | ||
539 | int err; | ||
540 | |||
541 | restart: | ||
542 | spin_lock(&nn->nfs_client_lock); | ||
543 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | ||
544 | /* Wait for initialisation to finish */ | ||
545 | if (clp->cl_cons_state == NFS_CS_INITING) { | ||
546 | atomic_inc(&clp->cl_count); | ||
547 | spin_unlock(&nn->nfs_client_lock); | ||
548 | err = nfs_wait_client_init_complete(clp); | ||
549 | nfs_put_client(clp); | ||
550 | if (err) | ||
551 | return NULL; | ||
552 | goto restart; | ||
553 | } | ||
554 | /* Skip nfs_clients that failed to initialise */ | ||
555 | if (clp->cl_cons_state < 0) | ||
556 | continue; | ||
557 | smp_rmb(); | ||
558 | if (clp->rpc_ops != &nfs_v4_clientops) | ||
559 | continue; | ||
560 | cl_dentry = clp->cl_idmap->idmap_pipe->dentry; | ||
561 | if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) || | ||
562 | ((event == RPC_PIPEFS_UMOUNT) && !cl_dentry)) | ||
563 | continue; | ||
564 | atomic_inc(&clp->cl_count); | ||
565 | spin_unlock(&nn->nfs_client_lock); | ||
566 | return clp; | ||
567 | } | ||
568 | spin_unlock(&nn->nfs_client_lock); | ||
569 | return NULL; | ||
570 | } | ||
571 | |||
572 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
573 | void *ptr) | ||
574 | { | ||
575 | struct super_block *sb = ptr; | ||
576 | struct nfs_client *clp; | ||
577 | int error = 0; | ||
578 | |||
579 | if (!try_module_get(THIS_MODULE)) | ||
580 | return 0; | ||
581 | |||
582 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { | ||
583 | error = __rpc_pipefs_event(clp, event, sb); | ||
584 | nfs_put_client(clp); | ||
585 | if (error) | ||
586 | break; | ||
587 | } | ||
588 | module_put(THIS_MODULE); | ||
589 | return error; | ||
590 | } | ||
591 | |||
592 | #define PIPEFS_NFS_PRIO 1 | ||
593 | |||
594 | static struct notifier_block nfs_idmap_block = { | ||
595 | .notifier_call = rpc_pipefs_event, | ||
596 | .priority = SUNRPC_PIPEFS_NFS_PRIO, | ||
597 | }; | ||
598 | |||
599 | int nfs_idmap_init(void) | 490 | int nfs_idmap_init(void) |
600 | { | 491 | { |
601 | int ret; | 492 | int ret; |
602 | ret = nfs_idmap_init_keyring(); | 493 | ret = nfs_idmap_init_keyring(); |
603 | if (ret != 0) | 494 | if (ret != 0) |
604 | goto out; | 495 | goto out; |
605 | ret = rpc_pipefs_notifier_register(&nfs_idmap_block); | ||
606 | if (ret != 0) | ||
607 | nfs_idmap_quit_keyring(); | ||
608 | out: | 496 | out: |
609 | return ret; | 497 | return ret; |
610 | } | 498 | } |
611 | 499 | ||
612 | void nfs_idmap_quit(void) | 500 | void nfs_idmap_quit(void) |
613 | { | 501 | { |
614 | rpc_pipefs_notifier_unregister(&nfs_idmap_block); | ||
615 | nfs_idmap_quit_keyring(); | 502 | nfs_idmap_quit_keyring(); |
616 | } | 503 | } |
617 | 504 | ||
@@ -849,6 +736,7 @@ int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_ | |||
849 | if (!uid_valid(*uid)) | 736 | if (!uid_valid(*uid)) |
850 | ret = -ERANGE; | 737 | ret = -ERANGE; |
851 | } | 738 | } |
739 | trace_nfs4_map_name_to_uid(name, namelen, id, ret); | ||
852 | return ret; | 740 | return ret; |
853 | } | 741 | } |
854 | 742 | ||
@@ -865,6 +753,7 @@ int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size | |||
865 | if (!gid_valid(*gid)) | 753 | if (!gid_valid(*gid)) |
866 | ret = -ERANGE; | 754 | ret = -ERANGE; |
867 | } | 755 | } |
756 | trace_nfs4_map_group_to_gid(name, namelen, id, ret); | ||
868 | return ret; | 757 | return ret; |
869 | } | 758 | } |
870 | 759 | ||
@@ -879,6 +768,7 @@ int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, | |||
879 | ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap); | 768 | ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap); |
880 | if (ret < 0) | 769 | if (ret < 0) |
881 | ret = nfs_map_numeric_to_string(id, buf, buflen); | 770 | ret = nfs_map_numeric_to_string(id, buf, buflen); |
771 | trace_nfs4_map_uid_to_name(buf, ret, id, ret); | ||
882 | return ret; | 772 | return ret; |
883 | } | 773 | } |
884 | int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen) | 774 | int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen) |
@@ -892,5 +782,6 @@ int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, | |||
892 | ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap); | 782 | ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap); |
893 | if (ret < 0) | 783 | if (ret < 0) |
894 | ret = nfs_map_numeric_to_string(id, buf, buflen); | 784 | ret = nfs_map_numeric_to_string(id, buf, buflen); |
785 | trace_nfs4_map_gid_to_group(buf, ret, id, ret); | ||
895 | return ret; | 786 | return ret; |
896 | } | 787 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 941246f2b43d..87e797640828 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/compat.h> | 39 | #include <linux/compat.h> |
40 | #include <linux/freezer.h> | 40 | #include <linux/freezer.h> |
41 | #include <linux/crc32.h> | ||
42 | 41 | ||
43 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
44 | 43 | ||
@@ -52,6 +51,8 @@ | |||
52 | #include "nfs.h" | 51 | #include "nfs.h" |
53 | #include "netns.h" | 52 | #include "netns.h" |
54 | 53 | ||
54 | #include "nfstrace.h" | ||
55 | |||
55 | #define NFSDBG_FACILITY NFSDBG_VFS | 56 | #define NFSDBG_FACILITY NFSDBG_VFS |
56 | 57 | ||
57 | #define NFS_64_BIT_INODE_NUMBERS_ENABLED 1 | 58 | #define NFS_64_BIT_INODE_NUMBERS_ENABLED 1 |
@@ -503,6 +504,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
503 | if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) | 504 | if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) |
504 | return 0; | 505 | return 0; |
505 | 506 | ||
507 | trace_nfs_setattr_enter(inode); | ||
508 | |||
506 | /* Write all dirty data */ | 509 | /* Write all dirty data */ |
507 | if (S_ISREG(inode->i_mode)) { | 510 | if (S_ISREG(inode->i_mode)) { |
508 | nfs_inode_dio_wait(inode); | 511 | nfs_inode_dio_wait(inode); |
@@ -522,6 +525,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
522 | error = nfs_refresh_inode(inode, fattr); | 525 | error = nfs_refresh_inode(inode, fattr); |
523 | nfs_free_fattr(fattr); | 526 | nfs_free_fattr(fattr); |
524 | out: | 527 | out: |
528 | trace_nfs_setattr_exit(inode, error); | ||
525 | return error; | 529 | return error; |
526 | } | 530 | } |
527 | EXPORT_SYMBOL_GPL(nfs_setattr); | 531 | EXPORT_SYMBOL_GPL(nfs_setattr); |
@@ -591,6 +595,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
591 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; | 595 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
592 | int err; | 596 | int err; |
593 | 597 | ||
598 | trace_nfs_getattr_enter(inode); | ||
594 | /* Flush out writes to the server in order to update c/mtime. */ | 599 | /* Flush out writes to the server in order to update c/mtime. */ |
595 | if (S_ISREG(inode->i_mode)) { | 600 | if (S_ISREG(inode->i_mode)) { |
596 | nfs_inode_dio_wait(inode); | 601 | nfs_inode_dio_wait(inode); |
@@ -621,6 +626,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
621 | stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); | 626 | stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); |
622 | } | 627 | } |
623 | out: | 628 | out: |
629 | trace_nfs_getattr_exit(inode, err); | ||
624 | return err; | 630 | return err; |
625 | } | 631 | } |
626 | EXPORT_SYMBOL_GPL(nfs_getattr); | 632 | EXPORT_SYMBOL_GPL(nfs_getattr); |
@@ -875,6 +881,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
875 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 881 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
876 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 882 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
877 | 883 | ||
884 | trace_nfs_revalidate_inode_enter(inode); | ||
885 | |||
878 | if (is_bad_inode(inode)) | 886 | if (is_bad_inode(inode)) |
879 | goto out; | 887 | goto out; |
880 | if (NFS_STALE(inode)) | 888 | if (NFS_STALE(inode)) |
@@ -925,6 +933,7 @@ err_out: | |||
925 | nfs4_label_free(label); | 933 | nfs4_label_free(label); |
926 | out: | 934 | out: |
927 | nfs_free_fattr(fattr); | 935 | nfs_free_fattr(fattr); |
936 | trace_nfs_revalidate_inode_exit(inode, status); | ||
928 | return status; | 937 | return status; |
929 | } | 938 | } |
930 | 939 | ||
@@ -981,6 +990,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map | |||
981 | spin_unlock(&inode->i_lock); | 990 | spin_unlock(&inode->i_lock); |
982 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 991 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
983 | nfs_fscache_wait_on_invalidate(inode); | 992 | nfs_fscache_wait_on_invalidate(inode); |
993 | |||
984 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 994 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
985 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 995 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
986 | return 0; | 996 | return 0; |
@@ -1014,8 +1024,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1014 | if (ret < 0) | 1024 | if (ret < 0) |
1015 | goto out; | 1025 | goto out; |
1016 | } | 1026 | } |
1017 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | 1027 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
1028 | trace_nfs_invalidate_mapping_enter(inode); | ||
1018 | ret = nfs_invalidate_mapping(inode, mapping); | 1029 | ret = nfs_invalidate_mapping(inode, mapping); |
1030 | trace_nfs_invalidate_mapping_exit(inode, ret); | ||
1031 | } | ||
1032 | |||
1019 | out: | 1033 | out: |
1020 | return ret; | 1034 | return ret; |
1021 | } | 1035 | } |
@@ -1195,7 +1209,7 @@ u32 _nfs_display_fhandle_hash(const struct nfs_fh *fh) | |||
1195 | { | 1209 | { |
1196 | /* wireshark uses 32-bit AUTODIN crc and does a bitwise | 1210 | /* wireshark uses 32-bit AUTODIN crc and does a bitwise |
1197 | * not on the result */ | 1211 | * not on the result */ |
1198 | return ~crc32(0xFFFFFFFF, &fh->data[0], fh->size); | 1212 | return nfs_fhandle_hash(fh); |
1199 | } | 1213 | } |
1200 | 1214 | ||
1201 | /* | 1215 | /* |
@@ -1274,9 +1288,17 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
1274 | 1288 | ||
1275 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | 1289 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) |
1276 | { | 1290 | { |
1291 | int ret; | ||
1292 | |||
1293 | trace_nfs_refresh_inode_enter(inode); | ||
1294 | |||
1277 | if (nfs_inode_attrs_need_update(inode, fattr)) | 1295 | if (nfs_inode_attrs_need_update(inode, fattr)) |
1278 | return nfs_update_inode(inode, fattr); | 1296 | ret = nfs_update_inode(inode, fattr); |
1279 | return nfs_check_inode_attributes(inode, fattr); | 1297 | else |
1298 | ret = nfs_check_inode_attributes(inode, fattr); | ||
1299 | |||
1300 | trace_nfs_refresh_inode_exit(inode, ret); | ||
1301 | return ret; | ||
1280 | } | 1302 | } |
1281 | 1303 | ||
1282 | /** | 1304 | /** |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 3c8373f90ab3..d388302c005f 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "nfs4_fs.h" | 5 | #include "nfs4_fs.h" |
6 | #include <linux/mount.h> | 6 | #include <linux/mount.h> |
7 | #include <linux/security.h> | 7 | #include <linux/security.h> |
8 | #include <linux/crc32.h> | ||
8 | 9 | ||
9 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) | 10 | #define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) |
10 | 11 | ||
@@ -185,6 +186,8 @@ extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | |||
185 | int ds_addrlen, int ds_proto, | 186 | int ds_addrlen, int ds_proto, |
186 | unsigned int ds_timeo, | 187 | unsigned int ds_timeo, |
187 | unsigned int ds_retrans); | 188 | unsigned int ds_retrans); |
189 | extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *, | ||
190 | struct inode *); | ||
188 | #ifdef CONFIG_PROC_FS | 191 | #ifdef CONFIG_PROC_FS |
189 | extern int __init nfs_fs_proc_init(void); | 192 | extern int __init nfs_fs_proc_init(void); |
190 | extern void nfs_fs_proc_exit(void); | 193 | extern void nfs_fs_proc_exit(void); |
@@ -267,7 +270,7 @@ extern struct rpc_procinfo nfs4_procedures[]; | |||
267 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 270 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
268 | extern struct nfs_client *nfs_init_client(struct nfs_client *clp, | 271 | extern struct nfs_client *nfs_init_client(struct nfs_client *clp, |
269 | const struct rpc_timeout *timeparms, | 272 | const struct rpc_timeout *timeparms, |
270 | const char *ip_addr, rpc_authflavor_t authflavour); | 273 | const char *ip_addr); |
271 | 274 | ||
272 | /* dir.c */ | 275 | /* dir.c */ |
273 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, | 276 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, |
@@ -355,7 +358,7 @@ extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, | |||
355 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, | 358 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, |
356 | const char *); | 359 | const char *); |
357 | 360 | ||
358 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | 361 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool); |
359 | #endif | 362 | #endif |
360 | 363 | ||
361 | struct nfs_pgio_completion_ops; | 364 | struct nfs_pgio_completion_ops; |
@@ -430,6 +433,8 @@ void nfs_request_remove_commit_list(struct nfs_page *req, | |||
430 | void nfs_init_cinfo(struct nfs_commit_info *cinfo, | 433 | void nfs_init_cinfo(struct nfs_commit_info *cinfo, |
431 | struct inode *inode, | 434 | struct inode *inode, |
432 | struct nfs_direct_req *dreq); | 435 | struct nfs_direct_req *dreq); |
436 | int nfs_key_timeout_notify(struct file *filp, struct inode *inode); | ||
437 | bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx); | ||
433 | 438 | ||
434 | #ifdef CONFIG_MIGRATION | 439 | #ifdef CONFIG_MIGRATION |
435 | extern int nfs_migrate_page(struct address_space *, | 440 | extern int nfs_migrate_page(struct address_space *, |
@@ -451,8 +456,7 @@ extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq); | |||
451 | extern void __nfs4_read_done_cb(struct nfs_read_data *); | 456 | extern void __nfs4_read_done_cb(struct nfs_read_data *); |
452 | extern struct nfs_client *nfs4_init_client(struct nfs_client *clp, | 457 | extern struct nfs_client *nfs4_init_client(struct nfs_client *clp, |
453 | const struct rpc_timeout *timeparms, | 458 | const struct rpc_timeout *timeparms, |
454 | const char *ip_addr, | 459 | const char *ip_addr); |
455 | rpc_authflavor_t authflavour); | ||
456 | extern int nfs40_walk_client_list(struct nfs_client *clp, | 460 | extern int nfs40_walk_client_list(struct nfs_client *clp, |
457 | struct nfs_client **result, | 461 | struct nfs_client **result, |
458 | struct rpc_cred *cred); | 462 | struct rpc_cred *cred); |
@@ -575,3 +579,22 @@ u64 nfs_timespec_to_change_attr(const struct timespec *ts) | |||
575 | { | 579 | { |
576 | return ((u64)ts->tv_sec << 30) + ts->tv_nsec; | 580 | return ((u64)ts->tv_sec << 30) + ts->tv_nsec; |
577 | } | 581 | } |
582 | |||
583 | #ifdef CONFIG_CRC32 | ||
584 | /** | ||
585 | * nfs_fhandle_hash - calculate the crc32 hash for the filehandle | ||
586 | * @fh - pointer to filehandle | ||
587 | * | ||
588 | * returns a crc32 hash for the filehandle that is compatible with | ||
589 | * the one displayed by "wireshark". | ||
590 | */ | ||
591 | static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) | ||
592 | { | ||
593 | return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); | ||
594 | } | ||
595 | #else | ||
596 | static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) | ||
597 | { | ||
598 | return 0; | ||
599 | } | ||
600 | #endif | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index f5c84c3efbca..90cb10d7b693 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -336,8 +336,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
336 | data->arg.create.createmode = NFS3_CREATE_UNCHECKED; | 336 | data->arg.create.createmode = NFS3_CREATE_UNCHECKED; |
337 | if (flags & O_EXCL) { | 337 | if (flags & O_EXCL) { |
338 | data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE; | 338 | data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE; |
339 | data->arg.create.verifier[0] = jiffies; | 339 | data->arg.create.verifier[0] = cpu_to_be32(jiffies); |
340 | data->arg.create.verifier[1] = current->pid; | 340 | data->arg.create.verifier[1] = cpu_to_be32(current->pid); |
341 | } | 341 | } |
342 | 342 | ||
343 | sattr->ia_mode &= ~current_umask(); | 343 | sattr->ia_mode &= ~current_umask(); |
@@ -826,9 +826,10 @@ static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
826 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; | 826 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; |
827 | } | 827 | } |
828 | 828 | ||
829 | static void nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 829 | static int nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
830 | { | 830 | { |
831 | rpc_call_start(task); | 831 | rpc_call_start(task); |
832 | return 0; | ||
832 | } | 833 | } |
833 | 834 | ||
834 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | 835 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -847,9 +848,10 @@ static void nfs3_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
847 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE]; | 848 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE]; |
848 | } | 849 | } |
849 | 850 | ||
850 | static void nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 851 | static int nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
851 | { | 852 | { |
852 | rpc_call_start(task); | 853 | rpc_call_start(task); |
854 | return 0; | ||
853 | } | 855 | } |
854 | 856 | ||
855 | static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 857 | static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ee81e354bce7..f520a1113b38 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -38,17 +38,15 @@ struct nfs4_minor_version_ops { | |||
38 | u32 minor_version; | 38 | u32 minor_version; |
39 | unsigned init_caps; | 39 | unsigned init_caps; |
40 | 40 | ||
41 | int (*call_sync)(struct rpc_clnt *clnt, | 41 | int (*init_client)(struct nfs_client *); |
42 | struct nfs_server *server, | 42 | void (*shutdown_client)(struct nfs_client *); |
43 | struct rpc_message *msg, | ||
44 | struct nfs4_sequence_args *args, | ||
45 | struct nfs4_sequence_res *res); | ||
46 | bool (*match_stateid)(const nfs4_stateid *, | 43 | bool (*match_stateid)(const nfs4_stateid *, |
47 | const nfs4_stateid *); | 44 | const nfs4_stateid *); |
48 | int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, | 45 | int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, |
49 | struct nfs_fsinfo *); | 46 | struct nfs_fsinfo *); |
50 | int (*free_lock_state)(struct nfs_server *, | 47 | int (*free_lock_state)(struct nfs_server *, |
51 | struct nfs4_lock_state *); | 48 | struct nfs4_lock_state *); |
49 | const struct rpc_call_ops *call_sync_ops; | ||
52 | const struct nfs4_state_recovery_ops *reboot_recovery_ops; | 50 | const struct nfs4_state_recovery_ops *reboot_recovery_ops; |
53 | const struct nfs4_state_recovery_ops *nograce_recovery_ops; | 51 | const struct nfs4_state_recovery_ops *nograce_recovery_ops; |
54 | const struct nfs4_state_maintenance_ops *state_renewal_ops; | 52 | const struct nfs4_state_maintenance_ops *state_renewal_ops; |
@@ -135,6 +133,7 @@ struct nfs4_lock_state { | |||
135 | struct list_head ls_locks; /* Other lock stateids */ | 133 | struct list_head ls_locks; /* Other lock stateids */ |
136 | struct nfs4_state * ls_state; /* Pointer to open state */ | 134 | struct nfs4_state * ls_state; /* Pointer to open state */ |
137 | #define NFS_LOCK_INITIALIZED 0 | 135 | #define NFS_LOCK_INITIALIZED 0 |
136 | #define NFS_LOCK_LOST 1 | ||
138 | unsigned long ls_flags; | 137 | unsigned long ls_flags; |
139 | struct nfs_seqid_counter ls_seqid; | 138 | struct nfs_seqid_counter ls_seqid; |
140 | nfs4_stateid ls_stateid; | 139 | nfs4_stateid ls_stateid; |
@@ -193,7 +192,6 @@ struct nfs4_state_recovery_ops { | |||
193 | int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *); | 192 | int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *); |
194 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); | 193 | int (*recover_lock)(struct nfs4_state *, struct file_lock *); |
195 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); | 194 | int (*establish_clid)(struct nfs_client *, struct rpc_cred *); |
196 | struct rpc_cred * (*get_clid_cred)(struct nfs_client *); | ||
197 | int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *); | 195 | int (*reclaim_complete)(struct nfs_client *, struct rpc_cred *); |
198 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, | 196 | int (*detect_trunking)(struct nfs_client *, struct nfs_client **, |
199 | struct rpc_cred *); | 197 | struct rpc_cred *); |
@@ -223,7 +221,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, | |||
223 | /* nfs4proc.c */ | 221 | /* nfs4proc.c */ |
224 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); | 222 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
225 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); | 223 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
226 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 224 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); |
227 | extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, struct rpc_cred *cred); | 225 | extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, struct rpc_cred *cred); |
228 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); | 226 | extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred); |
229 | extern int nfs4_destroy_clientid(struct nfs_client *clp); | 227 | extern int nfs4_destroy_clientid(struct nfs_client *clp); |
@@ -248,9 +246,6 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser | |||
248 | return server->nfs_client->cl_session; | 246 | return server->nfs_client->cl_session; |
249 | } | 247 | } |
250 | 248 | ||
251 | extern int nfs4_setup_sequence(const struct nfs_server *server, | ||
252 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | ||
253 | struct rpc_task *task); | ||
254 | extern int nfs41_setup_sequence(struct nfs4_session *session, | 249 | extern int nfs41_setup_sequence(struct nfs4_session *session, |
255 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 250 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
256 | struct rpc_task *task); | 251 | struct rpc_task *task); |
@@ -273,18 +268,63 @@ is_ds_client(struct nfs_client *clp) | |||
273 | { | 268 | { |
274 | return clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS; | 269 | return clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS; |
275 | } | 270 | } |
276 | #else /* CONFIG_NFS_v4_1 */ | 271 | |
277 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) | 272 | static inline bool |
273 | _nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, | ||
274 | struct rpc_clnt **clntp, struct rpc_message *msg) | ||
278 | { | 275 | { |
279 | return NULL; | 276 | struct rpc_cred *newcred = NULL; |
277 | rpc_authflavor_t flavor; | ||
278 | |||
279 | if (test_bit(sp4_mode, &clp->cl_sp4_flags)) { | ||
280 | spin_lock(&clp->cl_lock); | ||
281 | if (clp->cl_machine_cred != NULL) | ||
282 | newcred = get_rpccred(clp->cl_machine_cred); | ||
283 | spin_unlock(&clp->cl_lock); | ||
284 | if (msg->rpc_cred) | ||
285 | put_rpccred(msg->rpc_cred); | ||
286 | msg->rpc_cred = newcred; | ||
287 | |||
288 | flavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
289 | WARN_ON(flavor != RPC_AUTH_GSS_KRB5I && | ||
290 | flavor != RPC_AUTH_GSS_KRB5P); | ||
291 | *clntp = clp->cl_rpcclient; | ||
292 | |||
293 | return true; | ||
294 | } | ||
295 | return false; | ||
280 | } | 296 | } |
281 | 297 | ||
282 | static inline int nfs4_setup_sequence(const struct nfs_server *server, | 298 | /* |
283 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 299 | * Function responsible for determining if an rpc_message should use the |
284 | struct rpc_task *task) | 300 | * machine cred under SP4_MACH_CRED and if so switching the credential and |
301 | * authflavor (using the nfs_client's rpc_clnt which will be krb5i/p). | ||
302 | * Should be called before rpc_call_sync/rpc_call_async. | ||
303 | */ | ||
304 | static inline void | ||
305 | nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, | ||
306 | struct rpc_clnt **clntp, struct rpc_message *msg) | ||
285 | { | 307 | { |
286 | rpc_call_start(task); | 308 | _nfs4_state_protect(clp, sp4_mode, clntp, msg); |
287 | return 0; | 309 | } |
310 | |||
311 | /* | ||
312 | * Special wrapper to nfs4_state_protect for write. | ||
313 | * If WRITE can use machine cred but COMMIT cannot, make sure all writes | ||
314 | * that use machine cred use NFS_FILE_SYNC. | ||
315 | */ | ||
316 | static inline void | ||
317 | nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp, | ||
318 | struct rpc_message *msg, struct nfs_write_data *wdata) | ||
319 | { | ||
320 | if (_nfs4_state_protect(clp, NFS_SP4_MACH_CRED_WRITE, clntp, msg) && | ||
321 | !test_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags)) | ||
322 | wdata->args.stable = NFS_FILE_SYNC; | ||
323 | } | ||
324 | #else /* CONFIG_NFS_v4_1 */ | ||
325 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) | ||
326 | { | ||
327 | return NULL; | ||
288 | } | 328 | } |
289 | 329 | ||
290 | static inline bool | 330 | static inline bool |
@@ -298,6 +338,18 @@ is_ds_client(struct nfs_client *clp) | |||
298 | { | 338 | { |
299 | return false; | 339 | return false; |
300 | } | 340 | } |
341 | |||
342 | static inline void | ||
343 | nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_flags, | ||
344 | struct rpc_clnt **clntp, struct rpc_message *msg) | ||
345 | { | ||
346 | } | ||
347 | |||
348 | static inline void | ||
349 | nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp, | ||
350 | struct rpc_message *msg, struct nfs_write_data *wdata) | ||
351 | { | ||
352 | } | ||
301 | #endif /* CONFIG_NFS_V4_1 */ | 353 | #endif /* CONFIG_NFS_V4_1 */ |
302 | 354 | ||
303 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; | 355 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; |
@@ -308,6 +360,10 @@ extern const u32 nfs4_pathconf_bitmap[3]; | |||
308 | extern const u32 nfs4_fsinfo_bitmap[3]; | 360 | extern const u32 nfs4_fsinfo_bitmap[3]; |
309 | extern const u32 nfs4_fs_locations_bitmap[3]; | 361 | extern const u32 nfs4_fs_locations_bitmap[3]; |
310 | 362 | ||
363 | void nfs40_shutdown_client(struct nfs_client *); | ||
364 | void nfs41_shutdown_client(struct nfs_client *); | ||
365 | int nfs40_init_client(struct nfs_client *); | ||
366 | int nfs41_init_client(struct nfs_client *); | ||
311 | void nfs4_free_client(struct nfs_client *); | 367 | void nfs4_free_client(struct nfs_client *); |
312 | 368 | ||
313 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *); | 369 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *); |
@@ -319,7 +375,7 @@ extern void nfs4_kill_renewd(struct nfs_client *); | |||
319 | extern void nfs4_renew_state(struct work_struct *); | 375 | extern void nfs4_renew_state(struct work_struct *); |
320 | 376 | ||
321 | /* nfs4state.c */ | 377 | /* nfs4state.c */ |
322 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp); | 378 | struct rpc_cred *nfs4_get_clid_cred(struct nfs_client *clp); |
323 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); | 379 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); |
324 | struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); | 380 | struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); |
325 | int nfs4_discover_server_trunking(struct nfs_client *clp, | 381 | int nfs4_discover_server_trunking(struct nfs_client *clp, |
@@ -327,7 +383,6 @@ int nfs4_discover_server_trunking(struct nfs_client *clp, | |||
327 | int nfs40_discover_server_trunking(struct nfs_client *clp, | 383 | int nfs40_discover_server_trunking(struct nfs_client *clp, |
328 | struct nfs_client **, struct rpc_cred *); | 384 | struct nfs_client **, struct rpc_cred *); |
329 | #if defined(CONFIG_NFS_V4_1) | 385 | #if defined(CONFIG_NFS_V4_1) |
330 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); | ||
331 | int nfs41_discover_server_trunking(struct nfs_client *clp, | 386 | int nfs41_discover_server_trunking(struct nfs_client *clp, |
332 | struct nfs_client **, struct rpc_cred *); | 387 | struct nfs_client **, struct rpc_cred *); |
333 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); | 388 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); |
@@ -382,6 +437,7 @@ struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct | |||
382 | extern bool nfs4_disable_idmapping; | 437 | extern bool nfs4_disable_idmapping; |
383 | extern unsigned short max_session_slots; | 438 | extern unsigned short max_session_slots; |
384 | extern unsigned short send_implementation_id; | 439 | extern unsigned short send_implementation_id; |
440 | extern bool recover_lost_locks; | ||
385 | 441 | ||
386 | #define NFS4_CLIENT_ID_UNIQ_LEN (64) | 442 | #define NFS4_CLIENT_ID_UNIQ_LEN (64) |
387 | extern char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN]; | 443 | extern char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN]; |
@@ -429,6 +485,8 @@ static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state) | |||
429 | 485 | ||
430 | #define nfs4_close_state(a, b) do { } while (0) | 486 | #define nfs4_close_state(a, b) do { } while (0) |
431 | #define nfs4_close_sync(a, b) do { } while (0) | 487 | #define nfs4_close_sync(a, b) do { } while (0) |
488 | #define nfs4_state_protect(a, b, c, d) do { } while (0) | ||
489 | #define nfs4_state_protect_write(a, b, c, d) do { } while (0) | ||
432 | 490 | ||
433 | #endif /* CONFIG_NFS_V4 */ | 491 | #endif /* CONFIG_NFS_V4 */ |
434 | #endif /* __LINUX_FS_NFS_NFS4_FS.H */ | 492 | #endif /* __LINUX_FS_NFS_NFS4_FS.H */ |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 90dce91dd5b5..a860ab566d6e 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -41,19 +41,138 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | #ifdef CONFIG_NFS_V4_1 | 43 | #ifdef CONFIG_NFS_V4_1 |
44 | static void nfs4_shutdown_session(struct nfs_client *clp) | 44 | /** |
45 | * Per auth flavor data server rpc clients | ||
46 | */ | ||
47 | struct nfs4_ds_server { | ||
48 | struct list_head list; /* ds_clp->cl_ds_clients */ | ||
49 | struct rpc_clnt *rpc_clnt; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * Common lookup case for DS I/O | ||
54 | */ | ||
55 | static struct nfs4_ds_server * | ||
56 | nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor) | ||
57 | { | ||
58 | struct nfs4_ds_server *dss; | ||
59 | |||
60 | rcu_read_lock(); | ||
61 | list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) { | ||
62 | if (dss->rpc_clnt->cl_auth->au_flavor != flavor) | ||
63 | continue; | ||
64 | goto out; | ||
65 | } | ||
66 | dss = NULL; | ||
67 | out: | ||
68 | rcu_read_unlock(); | ||
69 | return dss; | ||
70 | } | ||
71 | |||
72 | static struct nfs4_ds_server * | ||
73 | nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor, | ||
74 | struct nfs4_ds_server *new) | ||
75 | { | ||
76 | struct nfs4_ds_server *dss; | ||
77 | |||
78 | spin_lock(&ds_clp->cl_lock); | ||
79 | list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) { | ||
80 | if (dss->rpc_clnt->cl_auth->au_flavor != flavor) | ||
81 | continue; | ||
82 | goto out; | ||
83 | } | ||
84 | if (new) | ||
85 | list_add_rcu(&new->list, &ds_clp->cl_ds_clients); | ||
86 | dss = new; | ||
87 | out: | ||
88 | spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */ | ||
89 | return dss; | ||
90 | } | ||
91 | |||
92 | static struct nfs4_ds_server * | ||
93 | nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor) | ||
94 | { | ||
95 | struct nfs4_ds_server *dss; | ||
96 | |||
97 | dss = kmalloc(sizeof(*dss), GFP_NOFS); | ||
98 | if (dss == NULL) | ||
99 | return ERR_PTR(-ENOMEM); | ||
100 | |||
101 | dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor); | ||
102 | if (IS_ERR(dss->rpc_clnt)) { | ||
103 | int err = PTR_ERR(dss->rpc_clnt); | ||
104 | kfree (dss); | ||
105 | return ERR_PTR(err); | ||
106 | } | ||
107 | INIT_LIST_HEAD(&dss->list); | ||
108 | |||
109 | return dss; | ||
110 | } | ||
111 | |||
112 | static void | ||
113 | nfs4_free_ds_server(struct nfs4_ds_server *dss) | ||
114 | { | ||
115 | rpc_release_client(dss->rpc_clnt); | ||
116 | kfree(dss); | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Find or create a DS rpc client with th MDS server rpc client auth flavor | ||
121 | * in the nfs_client cl_ds_clients list. | ||
122 | */ | ||
123 | struct rpc_clnt * | ||
124 | nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode) | ||
125 | { | ||
126 | struct nfs4_ds_server *dss, *new; | ||
127 | rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor; | ||
128 | |||
129 | dss = nfs4_find_ds_client(ds_clp, flavor); | ||
130 | if (dss != NULL) | ||
131 | goto out; | ||
132 | new = nfs4_alloc_ds_server(ds_clp, flavor); | ||
133 | if (IS_ERR(new)) | ||
134 | return ERR_CAST(new); | ||
135 | dss = nfs4_add_ds_client(ds_clp, flavor, new); | ||
136 | if (dss != new) | ||
137 | nfs4_free_ds_server(new); | ||
138 | out: | ||
139 | return dss->rpc_clnt; | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client); | ||
142 | |||
143 | static void | ||
144 | nfs4_shutdown_ds_clients(struct nfs_client *clp) | ||
145 | { | ||
146 | struct nfs4_ds_server *dss; | ||
147 | LIST_HEAD(shutdown_list); | ||
148 | |||
149 | while (!list_empty(&clp->cl_ds_clients)) { | ||
150 | dss = list_entry(clp->cl_ds_clients.next, | ||
151 | struct nfs4_ds_server, list); | ||
152 | list_del(&dss->list); | ||
153 | rpc_shutdown_client(dss->rpc_clnt); | ||
154 | kfree (dss); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | void nfs41_shutdown_client(struct nfs_client *clp) | ||
45 | { | 159 | { |
46 | if (nfs4_has_session(clp)) { | 160 | if (nfs4_has_session(clp)) { |
161 | nfs4_shutdown_ds_clients(clp); | ||
47 | nfs4_destroy_session(clp->cl_session); | 162 | nfs4_destroy_session(clp->cl_session); |
48 | nfs4_destroy_clientid(clp); | 163 | nfs4_destroy_clientid(clp); |
49 | } | 164 | } |
50 | 165 | ||
51 | } | 166 | } |
52 | #else /* CONFIG_NFS_V4_1 */ | 167 | #endif /* CONFIG_NFS_V4_1 */ |
53 | static void nfs4_shutdown_session(struct nfs_client *clp) | 168 | |
169 | void nfs40_shutdown_client(struct nfs_client *clp) | ||
54 | { | 170 | { |
171 | if (clp->cl_slot_tbl) { | ||
172 | nfs4_release_slot_table(clp->cl_slot_tbl); | ||
173 | kfree(clp->cl_slot_tbl); | ||
174 | } | ||
55 | } | 175 | } |
56 | #endif /* CONFIG_NFS_V4_1 */ | ||
57 | 176 | ||
58 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | 177 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) |
59 | { | 178 | { |
@@ -73,6 +192,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
73 | 192 | ||
74 | spin_lock_init(&clp->cl_lock); | 193 | spin_lock_init(&clp->cl_lock); |
75 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 194 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
195 | INIT_LIST_HEAD(&clp->cl_ds_clients); | ||
76 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | 196 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
77 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 197 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
78 | clp->cl_minorversion = cl_init->minorversion; | 198 | clp->cl_minorversion = cl_init->minorversion; |
@@ -97,7 +217,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
97 | { | 217 | { |
98 | if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) | 218 | if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) |
99 | nfs4_kill_renewd(clp); | 219 | nfs4_kill_renewd(clp); |
100 | nfs4_shutdown_session(clp); | 220 | clp->cl_mvops->shutdown_client(clp); |
101 | nfs4_destroy_callback(clp); | 221 | nfs4_destroy_callback(clp); |
102 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) | 222 | if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) |
103 | nfs_idmap_delete(clp); | 223 | nfs_idmap_delete(clp); |
@@ -144,34 +264,77 @@ static int nfs4_init_callback(struct nfs_client *clp) | |||
144 | return 0; | 264 | return 0; |
145 | } | 265 | } |
146 | 266 | ||
267 | /** | ||
268 | * nfs40_init_client - nfs_client initialization tasks for NFSv4.0 | ||
269 | * @clp - nfs_client to initialize | ||
270 | * | ||
271 | * Returns zero on success, or a negative errno if some error occurred. | ||
272 | */ | ||
273 | int nfs40_init_client(struct nfs_client *clp) | ||
274 | { | ||
275 | struct nfs4_slot_table *tbl; | ||
276 | int ret; | ||
277 | |||
278 | tbl = kzalloc(sizeof(*tbl), GFP_NOFS); | ||
279 | if (tbl == NULL) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE, | ||
283 | "NFSv4.0 transport Slot table"); | ||
284 | if (ret) { | ||
285 | kfree(tbl); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | clp->cl_slot_tbl = tbl; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | #if defined(CONFIG_NFS_V4_1) | ||
294 | |||
295 | /** | ||
296 | * nfs41_init_client - nfs_client initialization tasks for NFSv4.1+ | ||
297 | * @clp - nfs_client to initialize | ||
298 | * | ||
299 | * Returns zero on success, or a negative errno if some error occurred. | ||
300 | */ | ||
301 | int nfs41_init_client(struct nfs_client *clp) | ||
302 | { | ||
303 | struct nfs4_session *session = NULL; | ||
304 | |||
305 | /* | ||
306 | * Create the session and mark it expired. | ||
307 | * When a SEQUENCE operation encounters the expired session | ||
308 | * it will do session recovery to initialize it. | ||
309 | */ | ||
310 | session = nfs4_alloc_session(clp); | ||
311 | if (!session) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | clp->cl_session = session; | ||
315 | |||
316 | /* | ||
317 | * The create session reply races with the server back | ||
318 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
319 | * so that the client back channel can find the | ||
320 | * nfs_client struct | ||
321 | */ | ||
322 | nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING); | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | #endif /* CONFIG_NFS_V4_1 */ | ||
327 | |||
147 | /* | 328 | /* |
148 | * Initialize the minor version specific parts of an NFS4 client record | 329 | * Initialize the minor version specific parts of an NFS4 client record |
149 | */ | 330 | */ |
150 | static int nfs4_init_client_minor_version(struct nfs_client *clp) | 331 | static int nfs4_init_client_minor_version(struct nfs_client *clp) |
151 | { | 332 | { |
152 | #if defined(CONFIG_NFS_V4_1) | 333 | int ret; |
153 | if (clp->cl_mvops->minor_version) { | ||
154 | struct nfs4_session *session = NULL; | ||
155 | /* | ||
156 | * Create the session and mark it expired. | ||
157 | * When a SEQUENCE operation encounters the expired session | ||
158 | * it will do session recovery to initialize it. | ||
159 | */ | ||
160 | session = nfs4_alloc_session(clp); | ||
161 | if (!session) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | clp->cl_session = session; | ||
165 | /* | ||
166 | * The create session reply races with the server back | ||
167 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
168 | * so that the client back channel can find the | ||
169 | * nfs_client struct | ||
170 | */ | ||
171 | nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING); | ||
172 | } | ||
173 | #endif /* CONFIG_NFS_V4_1 */ | ||
174 | 334 | ||
335 | ret = clp->cl_mvops->init_client(clp); | ||
336 | if (ret) | ||
337 | return ret; | ||
175 | return nfs4_init_callback(clp); | 338 | return nfs4_init_callback(clp); |
176 | } | 339 | } |
177 | 340 | ||
@@ -187,8 +350,7 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp) | |||
187 | */ | 350 | */ |
188 | struct nfs_client *nfs4_init_client(struct nfs_client *clp, | 351 | struct nfs_client *nfs4_init_client(struct nfs_client *clp, |
189 | const struct rpc_timeout *timeparms, | 352 | const struct rpc_timeout *timeparms, |
190 | const char *ip_addr, | 353 | const char *ip_addr) |
191 | rpc_authflavor_t authflavour) | ||
192 | { | 354 | { |
193 | char buf[INET6_ADDRSTRLEN + 1]; | 355 | char buf[INET6_ADDRSTRLEN + 1]; |
194 | struct nfs_client *old; | 356 | struct nfs_client *old; |
@@ -723,7 +885,7 @@ static void nfs4_session_set_rwsize(struct nfs_server *server) | |||
723 | } | 885 | } |
724 | 886 | ||
725 | static int nfs4_server_common_setup(struct nfs_server *server, | 887 | static int nfs4_server_common_setup(struct nfs_server *server, |
726 | struct nfs_fh *mntfh) | 888 | struct nfs_fh *mntfh, bool auth_probe) |
727 | { | 889 | { |
728 | struct nfs_fattr *fattr; | 890 | struct nfs_fattr *fattr; |
729 | int error; | 891 | int error; |
@@ -755,7 +917,7 @@ static int nfs4_server_common_setup(struct nfs_server *server, | |||
755 | 917 | ||
756 | 918 | ||
757 | /* Probe the root fh to retrieve its FSID and filehandle */ | 919 | /* Probe the root fh to retrieve its FSID and filehandle */ |
758 | error = nfs4_get_rootfh(server, mntfh); | 920 | error = nfs4_get_rootfh(server, mntfh, auth_probe); |
759 | if (error < 0) | 921 | if (error < 0) |
760 | goto out; | 922 | goto out; |
761 | 923 | ||
@@ -787,6 +949,7 @@ out: | |||
787 | static int nfs4_init_server(struct nfs_server *server, | 949 | static int nfs4_init_server(struct nfs_server *server, |
788 | const struct nfs_parsed_mount_data *data) | 950 | const struct nfs_parsed_mount_data *data) |
789 | { | 951 | { |
952 | rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; | ||
790 | struct rpc_timeout timeparms; | 953 | struct rpc_timeout timeparms; |
791 | int error; | 954 | int error; |
792 | 955 | ||
@@ -799,13 +962,16 @@ static int nfs4_init_server(struct nfs_server *server, | |||
799 | server->flags = data->flags; | 962 | server->flags = data->flags; |
800 | server->options = data->options; | 963 | server->options = data->options; |
801 | 964 | ||
965 | if (data->auth_flavor_len >= 1) | ||
966 | pseudoflavor = data->auth_flavors[0]; | ||
967 | |||
802 | /* Get a client record */ | 968 | /* Get a client record */ |
803 | error = nfs4_set_client(server, | 969 | error = nfs4_set_client(server, |
804 | data->nfs_server.hostname, | 970 | data->nfs_server.hostname, |
805 | (const struct sockaddr *)&data->nfs_server.address, | 971 | (const struct sockaddr *)&data->nfs_server.address, |
806 | data->nfs_server.addrlen, | 972 | data->nfs_server.addrlen, |
807 | data->client_address, | 973 | data->client_address, |
808 | data->auth_flavors[0], | 974 | pseudoflavor, |
809 | data->nfs_server.protocol, | 975 | data->nfs_server.protocol, |
810 | &timeparms, | 976 | &timeparms, |
811 | data->minorversion, | 977 | data->minorversion, |
@@ -825,7 +991,7 @@ static int nfs4_init_server(struct nfs_server *server, | |||
825 | 991 | ||
826 | server->port = data->nfs_server.port; | 992 | server->port = data->nfs_server.port; |
827 | 993 | ||
828 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); | 994 | error = nfs_init_server_rpcclient(server, &timeparms, pseudoflavor); |
829 | 995 | ||
830 | error: | 996 | error: |
831 | /* Done */ | 997 | /* Done */ |
@@ -843,6 +1009,7 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, | |||
843 | struct nfs_subversion *nfs_mod) | 1009 | struct nfs_subversion *nfs_mod) |
844 | { | 1010 | { |
845 | struct nfs_server *server; | 1011 | struct nfs_server *server; |
1012 | bool auth_probe; | ||
846 | int error; | 1013 | int error; |
847 | 1014 | ||
848 | dprintk("--> nfs4_create_server()\n"); | 1015 | dprintk("--> nfs4_create_server()\n"); |
@@ -851,12 +1018,14 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, | |||
851 | if (!server) | 1018 | if (!server) |
852 | return ERR_PTR(-ENOMEM); | 1019 | return ERR_PTR(-ENOMEM); |
853 | 1020 | ||
1021 | auth_probe = mount_info->parsed->auth_flavor_len < 1; | ||
1022 | |||
854 | /* set up the general RPC client */ | 1023 | /* set up the general RPC client */ |
855 | error = nfs4_init_server(server, mount_info->parsed); | 1024 | error = nfs4_init_server(server, mount_info->parsed); |
856 | if (error < 0) | 1025 | if (error < 0) |
857 | goto error; | 1026 | goto error; |
858 | 1027 | ||
859 | error = nfs4_server_common_setup(server, mount_info->mntfh); | 1028 | error = nfs4_server_common_setup(server, mount_info->mntfh, auth_probe); |
860 | if (error < 0) | 1029 | if (error < 0) |
861 | goto error; | 1030 | goto error; |
862 | 1031 | ||
@@ -909,7 +1078,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
909 | if (error < 0) | 1078 | if (error < 0) |
910 | goto error; | 1079 | goto error; |
911 | 1080 | ||
912 | error = nfs4_server_common_setup(server, mntfh); | 1081 | error = nfs4_server_common_setup(server, mntfh, |
1082 | !(parent_server->flags & NFS_MOUNT_SECFLAVOUR)); | ||
913 | if (error < 0) | 1083 | if (error < 0) |
914 | goto error; | 1084 | goto error; |
915 | 1085 | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 17ed87ef9de8..b86464ba25e1 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "internal.h" | 39 | #include "internal.h" |
40 | #include "delegation.h" | 40 | #include "delegation.h" |
41 | #include "nfs4filelayout.h" | 41 | #include "nfs4filelayout.h" |
42 | #include "nfs4trace.h" | ||
42 | 43 | ||
43 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 44 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
44 | 45 | ||
@@ -247,6 +248,7 @@ static int filelayout_read_done_cb(struct rpc_task *task, | |||
247 | struct nfs_pgio_header *hdr = data->header; | 248 | struct nfs_pgio_header *hdr = data->header; |
248 | int err; | 249 | int err; |
249 | 250 | ||
251 | trace_nfs4_pnfs_read(data, task->tk_status); | ||
250 | err = filelayout_async_handle_error(task, data->args.context->state, | 252 | err = filelayout_async_handle_error(task, data->args.context->state, |
251 | data->ds_clp, hdr->lseg); | 253 | data->ds_clp, hdr->lseg); |
252 | 254 | ||
@@ -363,6 +365,7 @@ static int filelayout_write_done_cb(struct rpc_task *task, | |||
363 | struct nfs_pgio_header *hdr = data->header; | 365 | struct nfs_pgio_header *hdr = data->header; |
364 | int err; | 366 | int err; |
365 | 367 | ||
368 | trace_nfs4_pnfs_write(data, task->tk_status); | ||
366 | err = filelayout_async_handle_error(task, data->args.context->state, | 369 | err = filelayout_async_handle_error(task, data->args.context->state, |
367 | data->ds_clp, hdr->lseg); | 370 | data->ds_clp, hdr->lseg); |
368 | 371 | ||
@@ -395,6 +398,7 @@ static int filelayout_commit_done_cb(struct rpc_task *task, | |||
395 | { | 398 | { |
396 | int err; | 399 | int err; |
397 | 400 | ||
401 | trace_nfs4_pnfs_commit_ds(data, task->tk_status); | ||
398 | err = filelayout_async_handle_error(task, NULL, data->ds_clp, | 402 | err = filelayout_async_handle_error(task, NULL, data->ds_clp, |
399 | data->lseg); | 403 | data->lseg); |
400 | 404 | ||
@@ -524,6 +528,7 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
524 | struct nfs_pgio_header *hdr = data->header; | 528 | struct nfs_pgio_header *hdr = data->header; |
525 | struct pnfs_layout_segment *lseg = hdr->lseg; | 529 | struct pnfs_layout_segment *lseg = hdr->lseg; |
526 | struct nfs4_pnfs_ds *ds; | 530 | struct nfs4_pnfs_ds *ds; |
531 | struct rpc_clnt *ds_clnt; | ||
527 | loff_t offset = data->args.offset; | 532 | loff_t offset = data->args.offset; |
528 | u32 j, idx; | 533 | u32 j, idx; |
529 | struct nfs_fh *fh; | 534 | struct nfs_fh *fh; |
@@ -538,6 +543,11 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
538 | ds = nfs4_fl_prepare_ds(lseg, idx); | 543 | ds = nfs4_fl_prepare_ds(lseg, idx); |
539 | if (!ds) | 544 | if (!ds) |
540 | return PNFS_NOT_ATTEMPTED; | 545 | return PNFS_NOT_ATTEMPTED; |
546 | |||
547 | ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode); | ||
548 | if (IS_ERR(ds_clnt)) | ||
549 | return PNFS_NOT_ATTEMPTED; | ||
550 | |||
541 | dprintk("%s USE DS: %s cl_count %d\n", __func__, | 551 | dprintk("%s USE DS: %s cl_count %d\n", __func__, |
542 | ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); | 552 | ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); |
543 | 553 | ||
@@ -552,7 +562,7 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
552 | data->mds_offset = offset; | 562 | data->mds_offset = offset; |
553 | 563 | ||
554 | /* Perform an asynchronous read to ds */ | 564 | /* Perform an asynchronous read to ds */ |
555 | nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, | 565 | nfs_initiate_read(ds_clnt, data, |
556 | &filelayout_read_call_ops, RPC_TASK_SOFTCONN); | 566 | &filelayout_read_call_ops, RPC_TASK_SOFTCONN); |
557 | return PNFS_ATTEMPTED; | 567 | return PNFS_ATTEMPTED; |
558 | } | 568 | } |
@@ -564,6 +574,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
564 | struct nfs_pgio_header *hdr = data->header; | 574 | struct nfs_pgio_header *hdr = data->header; |
565 | struct pnfs_layout_segment *lseg = hdr->lseg; | 575 | struct pnfs_layout_segment *lseg = hdr->lseg; |
566 | struct nfs4_pnfs_ds *ds; | 576 | struct nfs4_pnfs_ds *ds; |
577 | struct rpc_clnt *ds_clnt; | ||
567 | loff_t offset = data->args.offset; | 578 | loff_t offset = data->args.offset; |
568 | u32 j, idx; | 579 | u32 j, idx; |
569 | struct nfs_fh *fh; | 580 | struct nfs_fh *fh; |
@@ -574,6 +585,11 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
574 | ds = nfs4_fl_prepare_ds(lseg, idx); | 585 | ds = nfs4_fl_prepare_ds(lseg, idx); |
575 | if (!ds) | 586 | if (!ds) |
576 | return PNFS_NOT_ATTEMPTED; | 587 | return PNFS_NOT_ATTEMPTED; |
588 | |||
589 | ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode); | ||
590 | if (IS_ERR(ds_clnt)) | ||
591 | return PNFS_NOT_ATTEMPTED; | ||
592 | |||
577 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", | 593 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", |
578 | __func__, hdr->inode->i_ino, sync, (size_t) data->args.count, | 594 | __func__, hdr->inode->i_ino, sync, (size_t) data->args.count, |
579 | offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); | 595 | offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); |
@@ -591,7 +607,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
591 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | 607 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); |
592 | 608 | ||
593 | /* Perform an asynchronous write */ | 609 | /* Perform an asynchronous write */ |
594 | nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, | 610 | nfs_initiate_write(ds_clnt, data, |
595 | &filelayout_write_call_ops, sync, | 611 | &filelayout_write_call_ops, sync, |
596 | RPC_TASK_SOFTCONN); | 612 | RPC_TASK_SOFTCONN); |
597 | return PNFS_ATTEMPTED; | 613 | return PNFS_ATTEMPTED; |
@@ -1101,16 +1117,19 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how) | |||
1101 | { | 1117 | { |
1102 | struct pnfs_layout_segment *lseg = data->lseg; | 1118 | struct pnfs_layout_segment *lseg = data->lseg; |
1103 | struct nfs4_pnfs_ds *ds; | 1119 | struct nfs4_pnfs_ds *ds; |
1120 | struct rpc_clnt *ds_clnt; | ||
1104 | u32 idx; | 1121 | u32 idx; |
1105 | struct nfs_fh *fh; | 1122 | struct nfs_fh *fh; |
1106 | 1123 | ||
1107 | idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); | 1124 | idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); |
1108 | ds = nfs4_fl_prepare_ds(lseg, idx); | 1125 | ds = nfs4_fl_prepare_ds(lseg, idx); |
1109 | if (!ds) { | 1126 | if (!ds) |
1110 | prepare_to_resend_writes(data); | 1127 | goto out_err; |
1111 | filelayout_commit_release(data); | 1128 | |
1112 | return -EAGAIN; | 1129 | ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, data->inode); |
1113 | } | 1130 | if (IS_ERR(ds_clnt)) |
1131 | goto out_err; | ||
1132 | |||
1114 | dprintk("%s ino %lu, how %d cl_count %d\n", __func__, | 1133 | dprintk("%s ino %lu, how %d cl_count %d\n", __func__, |
1115 | data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count)); | 1134 | data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count)); |
1116 | data->commit_done_cb = filelayout_commit_done_cb; | 1135 | data->commit_done_cb = filelayout_commit_done_cb; |
@@ -1119,9 +1138,13 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how) | |||
1119 | fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); | 1138 | fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); |
1120 | if (fh) | 1139 | if (fh) |
1121 | data->args.fh = fh; | 1140 | data->args.fh = fh; |
1122 | return nfs_initiate_commit(ds->ds_clp->cl_rpcclient, data, | 1141 | return nfs_initiate_commit(ds_clnt, data, |
1123 | &filelayout_commit_call_ops, how, | 1142 | &filelayout_commit_call_ops, how, |
1124 | RPC_TASK_SOFTCONN); | 1143 | RPC_TASK_SOFTCONN); |
1144 | out_err: | ||
1145 | prepare_to_resend_writes(data); | ||
1146 | filelayout_commit_release(data); | ||
1147 | return -EAGAIN; | ||
1125 | } | 1148 | } |
1126 | 1149 | ||
1127 | static int | 1150 | static int |
diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c index 549462e5b9b0..c0b3a16b4a00 100644 --- a/fs/nfs/nfs4getroot.c +++ b/fs/nfs/nfs4getroot.c | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 10 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
11 | 11 | ||
12 | int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) | 12 | int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe) |
13 | { | 13 | { |
14 | struct nfs_fsinfo fsinfo; | 14 | struct nfs_fsinfo fsinfo; |
15 | int ret = -ENOMEM; | 15 | int ret = -ENOMEM; |
@@ -21,7 +21,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) | |||
21 | goto out; | 21 | goto out; |
22 | 22 | ||
23 | /* Start by getting the root filehandle from the server */ | 23 | /* Start by getting the root filehandle from the server */ |
24 | ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo); | 24 | ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, auth_probe); |
25 | if (ret < 0) { | 25 | if (ret < 0) { |
26 | dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); | 26 | dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); |
27 | goto out; | 27 | goto out; |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index cdb0b41a4810..2288cd3c9278 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
12 | #include <linux/namei.h> | 12 | #include <linux/namei.h> |
13 | #include <linux/nfs_fs.h> | 13 | #include <linux/nfs_fs.h> |
14 | #include <linux/nfs_mount.h> | ||
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/string.h> | 16 | #include <linux/string.h> |
16 | #include <linux/sunrpc/clnt.h> | 17 | #include <linux/sunrpc/clnt.h> |
@@ -369,21 +370,33 @@ out: | |||
369 | struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, | 370 | struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, |
370 | struct nfs_fh *fh, struct nfs_fattr *fattr) | 371 | struct nfs_fh *fh, struct nfs_fattr *fattr) |
371 | { | 372 | { |
373 | rpc_authflavor_t flavor = server->client->cl_auth->au_flavor; | ||
372 | struct dentry *parent = dget_parent(dentry); | 374 | struct dentry *parent = dget_parent(dentry); |
375 | struct inode *dir = parent->d_inode; | ||
376 | struct qstr *name = &dentry->d_name; | ||
373 | struct rpc_clnt *client; | 377 | struct rpc_clnt *client; |
374 | struct vfsmount *mnt; | 378 | struct vfsmount *mnt; |
375 | 379 | ||
376 | /* Look it up again to get its attributes and sec flavor */ | 380 | /* Look it up again to get its attributes and sec flavor */ |
377 | client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr); | 381 | client = nfs4_proc_lookup_mountpoint(dir, name, fh, fattr); |
378 | dput(parent); | 382 | dput(parent); |
379 | if (IS_ERR(client)) | 383 | if (IS_ERR(client)) |
380 | return ERR_CAST(client); | 384 | return ERR_CAST(client); |
381 | 385 | ||
382 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 386 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
383 | mnt = nfs_do_refmount(client, dentry); | 387 | mnt = nfs_do_refmount(client, dentry); |
384 | else | 388 | goto out; |
385 | mnt = nfs_do_submount(dentry, fh, fattr, client->cl_auth->au_flavor); | 389 | } |
386 | 390 | ||
391 | if (client->cl_auth->au_flavor != flavor) | ||
392 | flavor = client->cl_auth->au_flavor; | ||
393 | else if (!(server->flags & NFS_MOUNT_SECFLAVOUR)) { | ||
394 | rpc_authflavor_t new = nfs4_negotiate_security(dir, name); | ||
395 | if ((int)new >= 0) | ||
396 | flavor = new; | ||
397 | } | ||
398 | mnt = nfs_do_submount(dentry, fh, fattr, flavor); | ||
399 | out: | ||
387 | rpc_shutdown_client(client); | 400 | rpc_shutdown_client(client); |
388 | return mnt; | 401 | return mnt; |
389 | } | 402 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 108a774095f7..39b6cf2d1683 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -66,6 +66,8 @@ | |||
66 | #include "nfs4session.h" | 66 | #include "nfs4session.h" |
67 | #include "fscache.h" | 67 | #include "fscache.h" |
68 | 68 | ||
69 | #include "nfs4trace.h" | ||
70 | |||
69 | #define NFSDBG_FACILITY NFSDBG_PROC | 71 | #define NFSDBG_FACILITY NFSDBG_PROC |
70 | 72 | ||
71 | #define NFS4_POLL_RETRY_MIN (HZ/10) | 73 | #define NFS4_POLL_RETRY_MIN (HZ/10) |
@@ -150,6 +152,7 @@ static int nfs4_map_errors(int err) | |||
150 | case -NFS4ERR_RECALLCONFLICT: | 152 | case -NFS4ERR_RECALLCONFLICT: |
151 | return -EREMOTEIO; | 153 | return -EREMOTEIO; |
152 | case -NFS4ERR_WRONGSEC: | 154 | case -NFS4ERR_WRONGSEC: |
155 | case -NFS4ERR_WRONG_CRED: | ||
153 | return -EPERM; | 156 | return -EPERM; |
154 | case -NFS4ERR_BADOWNER: | 157 | case -NFS4ERR_BADOWNER: |
155 | case -NFS4ERR_BADNAME: | 158 | case -NFS4ERR_BADNAME: |
@@ -433,6 +436,20 @@ wait_on_recovery: | |||
433 | return ret; | 436 | return ret; |
434 | } | 437 | } |
435 | 438 | ||
439 | /* | ||
440 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected | ||
441 | * or 'false' otherwise. | ||
442 | */ | ||
443 | static bool _nfs4_is_integrity_protected(struct nfs_client *clp) | ||
444 | { | ||
445 | rpc_authflavor_t flavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
446 | |||
447 | if (flavor == RPC_AUTH_GSS_KRB5I || | ||
448 | flavor == RPC_AUTH_GSS_KRB5P) | ||
449 | return true; | ||
450 | |||
451 | return false; | ||
452 | } | ||
436 | 453 | ||
437 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) | 454 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) |
438 | { | 455 | { |
@@ -447,6 +464,88 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
447 | do_renew_lease(server->nfs_client, timestamp); | 464 | do_renew_lease(server->nfs_client, timestamp); |
448 | } | 465 | } |
449 | 466 | ||
467 | struct nfs4_call_sync_data { | ||
468 | const struct nfs_server *seq_server; | ||
469 | struct nfs4_sequence_args *seq_args; | ||
470 | struct nfs4_sequence_res *seq_res; | ||
471 | }; | ||
472 | |||
473 | static void nfs4_init_sequence(struct nfs4_sequence_args *args, | ||
474 | struct nfs4_sequence_res *res, int cache_reply) | ||
475 | { | ||
476 | args->sa_slot = NULL; | ||
477 | args->sa_cache_this = cache_reply; | ||
478 | args->sa_privileged = 0; | ||
479 | |||
480 | res->sr_slot = NULL; | ||
481 | } | ||
482 | |||
483 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
484 | { | ||
485 | args->sa_privileged = 1; | ||
486 | } | ||
487 | |||
488 | static int nfs40_setup_sequence(const struct nfs_server *server, | ||
489 | struct nfs4_sequence_args *args, | ||
490 | struct nfs4_sequence_res *res, | ||
491 | struct rpc_task *task) | ||
492 | { | ||
493 | struct nfs4_slot_table *tbl = server->nfs_client->cl_slot_tbl; | ||
494 | struct nfs4_slot *slot; | ||
495 | |||
496 | /* slot already allocated? */ | ||
497 | if (res->sr_slot != NULL) | ||
498 | goto out_start; | ||
499 | |||
500 | spin_lock(&tbl->slot_tbl_lock); | ||
501 | if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged) | ||
502 | goto out_sleep; | ||
503 | |||
504 | slot = nfs4_alloc_slot(tbl); | ||
505 | if (IS_ERR(slot)) { | ||
506 | if (slot == ERR_PTR(-ENOMEM)) | ||
507 | task->tk_timeout = HZ >> 2; | ||
508 | goto out_sleep; | ||
509 | } | ||
510 | spin_unlock(&tbl->slot_tbl_lock); | ||
511 | |||
512 | args->sa_slot = slot; | ||
513 | res->sr_slot = slot; | ||
514 | |||
515 | out_start: | ||
516 | rpc_call_start(task); | ||
517 | return 0; | ||
518 | |||
519 | out_sleep: | ||
520 | if (args->sa_privileged) | ||
521 | rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task, | ||
522 | NULL, RPC_PRIORITY_PRIVILEGED); | ||
523 | else | ||
524 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
525 | spin_unlock(&tbl->slot_tbl_lock); | ||
526 | return -EAGAIN; | ||
527 | } | ||
528 | |||
529 | static int nfs40_sequence_done(struct rpc_task *task, | ||
530 | struct nfs4_sequence_res *res) | ||
531 | { | ||
532 | struct nfs4_slot *slot = res->sr_slot; | ||
533 | struct nfs4_slot_table *tbl; | ||
534 | |||
535 | if (!RPC_WAS_SENT(task)) | ||
536 | goto out; | ||
537 | |||
538 | tbl = slot->table; | ||
539 | spin_lock(&tbl->slot_tbl_lock); | ||
540 | if (!nfs41_wake_and_assign_slot(tbl, slot)) | ||
541 | nfs4_free_slot(tbl, slot); | ||
542 | spin_unlock(&tbl->slot_tbl_lock); | ||
543 | |||
544 | res->sr_slot = NULL; | ||
545 | out: | ||
546 | return 1; | ||
547 | } | ||
548 | |||
450 | #if defined(CONFIG_NFS_V4_1) | 549 | #if defined(CONFIG_NFS_V4_1) |
451 | 550 | ||
452 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | 551 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
@@ -506,6 +605,7 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
506 | interrupted = true; | 605 | interrupted = true; |
507 | } | 606 | } |
508 | 607 | ||
608 | trace_nfs4_sequence_done(session, res); | ||
509 | /* Check the SEQUENCE operation status */ | 609 | /* Check the SEQUENCE operation status */ |
510 | switch (res->sr_status) { | 610 | switch (res->sr_status) { |
511 | case 0: | 611 | case 0: |
@@ -591,25 +691,11 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
591 | { | 691 | { |
592 | if (res->sr_slot == NULL) | 692 | if (res->sr_slot == NULL) |
593 | return 1; | 693 | return 1; |
694 | if (!res->sr_slot->table->session) | ||
695 | return nfs40_sequence_done(task, res); | ||
594 | return nfs41_sequence_done(task, res); | 696 | return nfs41_sequence_done(task, res); |
595 | } | 697 | } |
596 | 698 | ||
597 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
598 | struct nfs4_sequence_res *res, int cache_reply) | ||
599 | { | ||
600 | args->sa_slot = NULL; | ||
601 | args->sa_cache_this = 0; | ||
602 | args->sa_privileged = 0; | ||
603 | if (cache_reply) | ||
604 | args->sa_cache_this = 1; | ||
605 | res->sr_slot = NULL; | ||
606 | } | ||
607 | |||
608 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
609 | { | ||
610 | args->sa_privileged = 1; | ||
611 | } | ||
612 | |||
613 | int nfs41_setup_sequence(struct nfs4_session *session, | 699 | int nfs41_setup_sequence(struct nfs4_session *session, |
614 | struct nfs4_sequence_args *args, | 700 | struct nfs4_sequence_args *args, |
615 | struct nfs4_sequence_res *res, | 701 | struct nfs4_sequence_res *res, |
@@ -647,7 +733,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
647 | 733 | ||
648 | args->sa_slot = slot; | 734 | args->sa_slot = slot; |
649 | 735 | ||
650 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, | 736 | dprintk("<-- %s slotid=%u seqid=%u\n", __func__, |
651 | slot->slot_nr, slot->seq_nr); | 737 | slot->slot_nr, slot->seq_nr); |
652 | 738 | ||
653 | res->sr_slot = slot; | 739 | res->sr_slot = slot; |
@@ -658,6 +744,7 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
658 | * set to 1 if an rpc level failure occurs. | 744 | * set to 1 if an rpc level failure occurs. |
659 | */ | 745 | */ |
660 | res->sr_status = 1; | 746 | res->sr_status = 1; |
747 | trace_nfs4_setup_sequence(session, args); | ||
661 | out_success: | 748 | out_success: |
662 | rpc_call_start(task); | 749 | rpc_call_start(task); |
663 | return 0; | 750 | return 0; |
@@ -673,38 +760,30 @@ out_sleep: | |||
673 | } | 760 | } |
674 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | 761 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); |
675 | 762 | ||
676 | int nfs4_setup_sequence(const struct nfs_server *server, | 763 | static int nfs4_setup_sequence(const struct nfs_server *server, |
677 | struct nfs4_sequence_args *args, | 764 | struct nfs4_sequence_args *args, |
678 | struct nfs4_sequence_res *res, | 765 | struct nfs4_sequence_res *res, |
679 | struct rpc_task *task) | 766 | struct rpc_task *task) |
680 | { | 767 | { |
681 | struct nfs4_session *session = nfs4_get_session(server); | 768 | struct nfs4_session *session = nfs4_get_session(server); |
682 | int ret = 0; | 769 | int ret = 0; |
683 | 770 | ||
684 | if (session == NULL) { | 771 | if (!session) |
685 | rpc_call_start(task); | 772 | return nfs40_setup_sequence(server, args, res, task); |
686 | goto out; | ||
687 | } | ||
688 | 773 | ||
689 | dprintk("--> %s clp %p session %p sr_slot %d\n", | 774 | dprintk("--> %s clp %p session %p sr_slot %u\n", |
690 | __func__, session->clp, session, res->sr_slot ? | 775 | __func__, session->clp, session, res->sr_slot ? |
691 | res->sr_slot->slot_nr : -1); | 776 | res->sr_slot->slot_nr : NFS4_NO_SLOT); |
692 | 777 | ||
693 | ret = nfs41_setup_sequence(session, args, res, task); | 778 | ret = nfs41_setup_sequence(session, args, res, task); |
694 | out: | 779 | |
695 | dprintk("<-- %s status=%d\n", __func__, ret); | 780 | dprintk("<-- %s status=%d\n", __func__, ret); |
696 | return ret; | 781 | return ret; |
697 | } | 782 | } |
698 | 783 | ||
699 | struct nfs41_call_sync_data { | ||
700 | const struct nfs_server *seq_server; | ||
701 | struct nfs4_sequence_args *seq_args; | ||
702 | struct nfs4_sequence_res *seq_res; | ||
703 | }; | ||
704 | |||
705 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | 784 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) |
706 | { | 785 | { |
707 | struct nfs41_call_sync_data *data = calldata; | 786 | struct nfs4_call_sync_data *data = calldata; |
708 | struct nfs4_session *session = nfs4_get_session(data->seq_server); | 787 | struct nfs4_session *session = nfs4_get_session(data->seq_server); |
709 | 788 | ||
710 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); | 789 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
@@ -714,7 +793,7 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | |||
714 | 793 | ||
715 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 794 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) |
716 | { | 795 | { |
717 | struct nfs41_call_sync_data *data = calldata; | 796 | struct nfs4_call_sync_data *data = calldata; |
718 | 797 | ||
719 | nfs41_sequence_done(task, data->seq_res); | 798 | nfs41_sequence_done(task, data->seq_res); |
720 | } | 799 | } |
@@ -724,6 +803,42 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { | |||
724 | .rpc_call_done = nfs41_call_sync_done, | 803 | .rpc_call_done = nfs41_call_sync_done, |
725 | }; | 804 | }; |
726 | 805 | ||
806 | #else /* !CONFIG_NFS_V4_1 */ | ||
807 | |||
808 | static int nfs4_setup_sequence(const struct nfs_server *server, | ||
809 | struct nfs4_sequence_args *args, | ||
810 | struct nfs4_sequence_res *res, | ||
811 | struct rpc_task *task) | ||
812 | { | ||
813 | return nfs40_setup_sequence(server, args, res, task); | ||
814 | } | ||
815 | |||
816 | static int nfs4_sequence_done(struct rpc_task *task, | ||
817 | struct nfs4_sequence_res *res) | ||
818 | { | ||
819 | return nfs40_sequence_done(task, res); | ||
820 | } | ||
821 | |||
822 | #endif /* !CONFIG_NFS_V4_1 */ | ||
823 | |||
824 | static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata) | ||
825 | { | ||
826 | struct nfs4_call_sync_data *data = calldata; | ||
827 | nfs4_setup_sequence(data->seq_server, | ||
828 | data->seq_args, data->seq_res, task); | ||
829 | } | ||
830 | |||
831 | static void nfs40_call_sync_done(struct rpc_task *task, void *calldata) | ||
832 | { | ||
833 | struct nfs4_call_sync_data *data = calldata; | ||
834 | nfs4_sequence_done(task, data->seq_res); | ||
835 | } | ||
836 | |||
837 | static const struct rpc_call_ops nfs40_call_sync_ops = { | ||
838 | .rpc_call_prepare = nfs40_call_sync_prepare, | ||
839 | .rpc_call_done = nfs40_call_sync_done, | ||
840 | }; | ||
841 | |||
727 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | 842 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, |
728 | struct nfs_server *server, | 843 | struct nfs_server *server, |
729 | struct rpc_message *msg, | 844 | struct rpc_message *msg, |
@@ -732,7 +847,8 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
732 | { | 847 | { |
733 | int ret; | 848 | int ret; |
734 | struct rpc_task *task; | 849 | struct rpc_task *task; |
735 | struct nfs41_call_sync_data data = { | 850 | struct nfs_client *clp = server->nfs_client; |
851 | struct nfs4_call_sync_data data = { | ||
736 | .seq_server = server, | 852 | .seq_server = server, |
737 | .seq_args = args, | 853 | .seq_args = args, |
738 | .seq_res = res, | 854 | .seq_res = res, |
@@ -740,7 +856,7 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
740 | struct rpc_task_setup task_setup = { | 856 | struct rpc_task_setup task_setup = { |
741 | .rpc_client = clnt, | 857 | .rpc_client = clnt, |
742 | .rpc_message = msg, | 858 | .rpc_message = msg, |
743 | .callback_ops = &nfs41_call_sync_ops, | 859 | .callback_ops = clp->cl_mvops->call_sync_ops, |
744 | .callback_data = &data | 860 | .callback_data = &data |
745 | }; | 861 | }; |
746 | 862 | ||
@@ -754,35 +870,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
754 | return ret; | 870 | return ret; |
755 | } | 871 | } |
756 | 872 | ||
757 | #else | ||
758 | static | ||
759 | void nfs41_init_sequence(struct nfs4_sequence_args *args, | ||
760 | struct nfs4_sequence_res *res, int cache_reply) | ||
761 | { | ||
762 | } | ||
763 | |||
764 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
765 | { | ||
766 | } | ||
767 | |||
768 | |||
769 | static int nfs4_sequence_done(struct rpc_task *task, | ||
770 | struct nfs4_sequence_res *res) | ||
771 | { | ||
772 | return 1; | ||
773 | } | ||
774 | #endif /* CONFIG_NFS_V4_1 */ | ||
775 | |||
776 | static | ||
777 | int _nfs4_call_sync(struct rpc_clnt *clnt, | ||
778 | struct nfs_server *server, | ||
779 | struct rpc_message *msg, | ||
780 | struct nfs4_sequence_args *args, | ||
781 | struct nfs4_sequence_res *res) | ||
782 | { | ||
783 | return rpc_call_sync(clnt, msg, 0); | ||
784 | } | ||
785 | |||
786 | static | 873 | static |
787 | int nfs4_call_sync(struct rpc_clnt *clnt, | 874 | int nfs4_call_sync(struct rpc_clnt *clnt, |
788 | struct nfs_server *server, | 875 | struct nfs_server *server, |
@@ -791,9 +878,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt, | |||
791 | struct nfs4_sequence_res *res, | 878 | struct nfs4_sequence_res *res, |
792 | int cache_reply) | 879 | int cache_reply) |
793 | { | 880 | { |
794 | nfs41_init_sequence(args, res, cache_reply); | 881 | nfs4_init_sequence(args, res, cache_reply); |
795 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, | 882 | return nfs4_call_sync_sequence(clnt, server, msg, args, res); |
796 | args, res); | ||
797 | } | 883 | } |
798 | 884 | ||
799 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 885 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
@@ -933,7 +1019,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
933 | p->o_arg.fh = NFS_FH(dentry->d_inode); | 1019 | p->o_arg.fh = NFS_FH(dentry->d_inode); |
934 | } | 1020 | } |
935 | if (attrs != NULL && attrs->ia_valid != 0) { | 1021 | if (attrs != NULL && attrs->ia_valid != 0) { |
936 | __be32 verf[2]; | 1022 | __u32 verf[2]; |
937 | 1023 | ||
938 | p->o_arg.u.attrs = &p->attrs; | 1024 | p->o_arg.u.attrs = &p->attrs; |
939 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); | 1025 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); |
@@ -1103,7 +1189,7 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat | |||
1103 | goto no_delegation; | 1189 | goto no_delegation; |
1104 | 1190 | ||
1105 | spin_lock(&deleg_cur->lock); | 1191 | spin_lock(&deleg_cur->lock); |
1106 | if (nfsi->delegation != deleg_cur || | 1192 | if (rcu_dereference(nfsi->delegation) != deleg_cur || |
1107 | test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) || | 1193 | test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) || |
1108 | (deleg_cur->type & fmode) != fmode) | 1194 | (deleg_cur->type & fmode) != fmode) |
1109 | goto no_delegation_unlock; | 1195 | goto no_delegation_unlock; |
@@ -1440,6 +1526,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state | |||
1440 | int err; | 1526 | int err; |
1441 | do { | 1527 | do { |
1442 | err = _nfs4_do_open_reclaim(ctx, state); | 1528 | err = _nfs4_do_open_reclaim(ctx, state); |
1529 | trace_nfs4_open_reclaim(ctx, 0, err); | ||
1443 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) | 1530 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) |
1444 | continue; | 1531 | continue; |
1445 | if (err != -NFS4ERR_DELAY) | 1532 | if (err != -NFS4ERR_DELAY) |
@@ -1524,10 +1611,20 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1524 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); | 1611 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); |
1525 | } | 1612 | } |
1526 | 1613 | ||
1614 | static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | ||
1615 | { | ||
1616 | struct nfs4_opendata *data = calldata; | ||
1617 | |||
1618 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | ||
1619 | &data->o_res.seq_res, task); | ||
1620 | } | ||
1621 | |||
1527 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1622 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
1528 | { | 1623 | { |
1529 | struct nfs4_opendata *data = calldata; | 1624 | struct nfs4_opendata *data = calldata; |
1530 | 1625 | ||
1626 | nfs40_sequence_done(task, &data->o_res.seq_res); | ||
1627 | |||
1531 | data->rpc_status = task->tk_status; | 1628 | data->rpc_status = task->tk_status; |
1532 | if (data->rpc_status == 0) { | 1629 | if (data->rpc_status == 0) { |
1533 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); | 1630 | nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid); |
@@ -1556,6 +1653,7 @@ out_free: | |||
1556 | } | 1653 | } |
1557 | 1654 | ||
1558 | static const struct rpc_call_ops nfs4_open_confirm_ops = { | 1655 | static const struct rpc_call_ops nfs4_open_confirm_ops = { |
1656 | .rpc_call_prepare = nfs4_open_confirm_prepare, | ||
1559 | .rpc_call_done = nfs4_open_confirm_done, | 1657 | .rpc_call_done = nfs4_open_confirm_done, |
1560 | .rpc_release = nfs4_open_confirm_release, | 1658 | .rpc_release = nfs4_open_confirm_release, |
1561 | }; | 1659 | }; |
@@ -1583,6 +1681,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
1583 | }; | 1681 | }; |
1584 | int status; | 1682 | int status; |
1585 | 1683 | ||
1684 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | ||
1586 | kref_get(&data->kref); | 1685 | kref_get(&data->kref); |
1587 | data->rpc_done = 0; | 1686 | data->rpc_done = 0; |
1588 | data->rpc_status = 0; | 1687 | data->rpc_status = 0; |
@@ -1742,7 +1841,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | |||
1742 | }; | 1841 | }; |
1743 | int status; | 1842 | int status; |
1744 | 1843 | ||
1745 | nfs41_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); | 1844 | nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1); |
1746 | kref_get(&data->kref); | 1845 | kref_get(&data->kref); |
1747 | data->rpc_done = 0; | 1846 | data->rpc_done = 0; |
1748 | data->rpc_status = 0; | 1847 | data->rpc_status = 0; |
@@ -1895,6 +1994,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state | |||
1895 | 1994 | ||
1896 | do { | 1995 | do { |
1897 | err = _nfs4_open_expired(ctx, state); | 1996 | err = _nfs4_open_expired(ctx, state); |
1997 | trace_nfs4_open_expired(ctx, 0, err); | ||
1898 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) | 1998 | if (nfs4_clear_cap_atomic_open_v1(server, err, &exception)) |
1899 | continue; | 1999 | continue; |
1900 | switch (err) { | 2000 | switch (err) { |
@@ -1944,6 +2044,7 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1944 | cred = get_rpccred(delegation->cred); | 2044 | cred = get_rpccred(delegation->cred); |
1945 | rcu_read_unlock(); | 2045 | rcu_read_unlock(); |
1946 | status = nfs41_test_stateid(server, stateid, cred); | 2046 | status = nfs41_test_stateid(server, stateid, cred); |
2047 | trace_nfs4_test_delegation_stateid(state, NULL, status); | ||
1947 | } else | 2048 | } else |
1948 | rcu_read_unlock(); | 2049 | rcu_read_unlock(); |
1949 | 2050 | ||
@@ -1986,6 +2087,7 @@ static int nfs41_check_open_stateid(struct nfs4_state *state) | |||
1986 | return -NFS4ERR_BAD_STATEID; | 2087 | return -NFS4ERR_BAD_STATEID; |
1987 | 2088 | ||
1988 | status = nfs41_test_stateid(server, stateid, cred); | 2089 | status = nfs41_test_stateid(server, stateid, cred); |
2090 | trace_nfs4_test_open_stateid(state, NULL, status); | ||
1989 | if (status != NFS_OK) { | 2091 | if (status != NFS_OK) { |
1990 | /* Free the stateid unless the server explicitly | 2092 | /* Free the stateid unless the server explicitly |
1991 | * informs us the stateid is unrecognized. */ | 2093 | * informs us the stateid is unrecognized. */ |
@@ -2197,6 +2299,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
2197 | do { | 2299 | do { |
2198 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); | 2300 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); |
2199 | res = ctx->state; | 2301 | res = ctx->state; |
2302 | trace_nfs4_open_file(ctx, flags, status); | ||
2200 | if (status == 0) | 2303 | if (status == 0) |
2201 | break; | 2304 | break; |
2202 | /* NOTE: BAD_SEQID means the server and client disagree about the | 2305 | /* NOTE: BAD_SEQID means the server and client disagree about the |
@@ -2310,6 +2413,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2310 | int err; | 2413 | int err; |
2311 | do { | 2414 | do { |
2312 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); | 2415 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); |
2416 | trace_nfs4_setattr(inode, err); | ||
2313 | switch (err) { | 2417 | switch (err) { |
2314 | case -NFS4ERR_OPENMODE: | 2418 | case -NFS4ERR_OPENMODE: |
2315 | if (!(sattr->ia_valid & ATTR_SIZE)) { | 2419 | if (!(sattr->ia_valid & ATTR_SIZE)) { |
@@ -2387,6 +2491,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2387 | dprintk("%s: begin!\n", __func__); | 2491 | dprintk("%s: begin!\n", __func__); |
2388 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) | 2492 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
2389 | return; | 2493 | return; |
2494 | trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status); | ||
2390 | /* hmm. we are done with the inode, and in the process of freeing | 2495 | /* hmm. we are done with the inode, and in the process of freeing |
2391 | * the state_owner. we keep this around to process errors | 2496 | * the state_owner. we keep this around to process errors |
2392 | */ | 2497 | */ |
@@ -2511,10 +2616,13 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) | |||
2511 | }; | 2616 | }; |
2512 | int status = -ENOMEM; | 2617 | int status = -ENOMEM; |
2513 | 2618 | ||
2619 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_CLEANUP, | ||
2620 | &task_setup_data.rpc_client, &msg); | ||
2621 | |||
2514 | calldata = kzalloc(sizeof(*calldata), gfp_mask); | 2622 | calldata = kzalloc(sizeof(*calldata), gfp_mask); |
2515 | if (calldata == NULL) | 2623 | if (calldata == NULL) |
2516 | goto out; | 2624 | goto out; |
2517 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1); | 2625 | nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1); |
2518 | calldata->inode = state->inode; | 2626 | calldata->inode = state->inode; |
2519 | calldata->state = state; | 2627 | calldata->state = state; |
2520 | calldata->arg.fh = NFS_FH(state->inode); | 2628 | calldata->arg.fh = NFS_FH(state->inode); |
@@ -2690,6 +2798,7 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2690 | int err; | 2798 | int err; |
2691 | do { | 2799 | do { |
2692 | err = _nfs4_lookup_root(server, fhandle, info); | 2800 | err = _nfs4_lookup_root(server, fhandle, info); |
2801 | trace_nfs4_lookup_root(server, fhandle, info->fattr, err); | ||
2693 | switch (err) { | 2802 | switch (err) { |
2694 | case 0: | 2803 | case 0: |
2695 | case -NFS4ERR_WRONGSEC: | 2804 | case -NFS4ERR_WRONGSEC: |
@@ -2705,10 +2814,13 @@ out: | |||
2705 | static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | 2814 | static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2706 | struct nfs_fsinfo *info, rpc_authflavor_t flavor) | 2815 | struct nfs_fsinfo *info, rpc_authflavor_t flavor) |
2707 | { | 2816 | { |
2817 | struct rpc_auth_create_args auth_args = { | ||
2818 | .pseudoflavor = flavor, | ||
2819 | }; | ||
2708 | struct rpc_auth *auth; | 2820 | struct rpc_auth *auth; |
2709 | int ret; | 2821 | int ret; |
2710 | 2822 | ||
2711 | auth = rpcauth_create(flavor, server->client); | 2823 | auth = rpcauth_create(&auth_args, server->client); |
2712 | if (IS_ERR(auth)) { | 2824 | if (IS_ERR(auth)) { |
2713 | ret = -EACCES; | 2825 | ret = -EACCES; |
2714 | goto out; | 2826 | goto out; |
@@ -2772,18 +2884,27 @@ static int nfs4_do_find_root_sec(struct nfs_server *server, | |||
2772 | * @server: initialized nfs_server handle | 2884 | * @server: initialized nfs_server handle |
2773 | * @fhandle: we fill in the pseudo-fs root file handle | 2885 | * @fhandle: we fill in the pseudo-fs root file handle |
2774 | * @info: we fill in an FSINFO struct | 2886 | * @info: we fill in an FSINFO struct |
2887 | * @auth_probe: probe the auth flavours | ||
2775 | * | 2888 | * |
2776 | * Returns zero on success, or a negative errno. | 2889 | * Returns zero on success, or a negative errno. |
2777 | */ | 2890 | */ |
2778 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, | 2891 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, |
2779 | struct nfs_fsinfo *info) | 2892 | struct nfs_fsinfo *info, |
2893 | bool auth_probe) | ||
2780 | { | 2894 | { |
2781 | int status; | 2895 | int status; |
2782 | 2896 | ||
2783 | status = nfs4_lookup_root(server, fhandle, info); | 2897 | switch (auth_probe) { |
2784 | if ((status == -NFS4ERR_WRONGSEC) && | 2898 | case false: |
2785 | !(server->flags & NFS_MOUNT_SECFLAVOUR)) | 2899 | status = nfs4_lookup_root(server, fhandle, info); |
2900 | if (status != -NFS4ERR_WRONGSEC) | ||
2901 | break; | ||
2902 | /* Did user force a 'sec=' mount option? */ | ||
2903 | if (server->flags & NFS_MOUNT_SECFLAVOUR) | ||
2904 | break; | ||
2905 | default: | ||
2786 | status = nfs4_do_find_root_sec(server, fhandle, info); | 2906 | status = nfs4_do_find_root_sec(server, fhandle, info); |
2907 | } | ||
2787 | 2908 | ||
2788 | if (status == 0) | 2909 | if (status == 0) |
2789 | status = nfs4_server_capabilities(server, fhandle); | 2910 | status = nfs4_server_capabilities(server, fhandle); |
@@ -2899,8 +3020,9 @@ static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2899 | struct nfs4_exception exception = { }; | 3020 | struct nfs4_exception exception = { }; |
2900 | int err; | 3021 | int err; |
2901 | do { | 3022 | do { |
2902 | err = nfs4_handle_exception(server, | 3023 | err = _nfs4_proc_getattr(server, fhandle, fattr, label); |
2903 | _nfs4_proc_getattr(server, fhandle, fattr, label), | 3024 | trace_nfs4_getattr(server, fhandle, fattr, err); |
3025 | err = nfs4_handle_exception(server, err, | ||
2904 | &exception); | 3026 | &exception); |
2905 | } while (exception.retry); | 3027 | } while (exception.retry); |
2906 | return err; | 3028 | return err; |
@@ -2940,10 +3062,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2940 | 3062 | ||
2941 | /* Deal with open(O_TRUNC) */ | 3063 | /* Deal with open(O_TRUNC) */ |
2942 | if (sattr->ia_valid & ATTR_OPEN) | 3064 | if (sattr->ia_valid & ATTR_OPEN) |
2943 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | 3065 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME); |
2944 | 3066 | ||
2945 | /* Optimization: if the end result is no change, don't RPC */ | 3067 | /* Optimization: if the end result is no change, don't RPC */ |
2946 | if ((sattr->ia_valid & ~(ATTR_FILE)) == 0) | 3068 | if ((sattr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) |
2947 | return 0; | 3069 | return 0; |
2948 | 3070 | ||
2949 | /* Search for an existing open(O_WRITE) file */ | 3071 | /* Search for an existing open(O_WRITE) file */ |
@@ -3020,6 +3142,7 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
3020 | int err; | 3142 | int err; |
3021 | do { | 3143 | do { |
3022 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); | 3144 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); |
3145 | trace_nfs4_lookup(dir, name, err); | ||
3023 | switch (err) { | 3146 | switch (err) { |
3024 | case -NFS4ERR_BADNAME: | 3147 | case -NFS4ERR_BADNAME: |
3025 | err = -ENOENT; | 3148 | err = -ENOENT; |
@@ -3031,7 +3154,9 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
3031 | err = -EPERM; | 3154 | err = -EPERM; |
3032 | if (client != *clnt) | 3155 | if (client != *clnt) |
3033 | goto out; | 3156 | goto out; |
3034 | 3157 | /* No security negotiation if the user specified 'sec=' */ | |
3158 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_SECFLAVOUR) | ||
3159 | goto out; | ||
3035 | client = nfs4_create_sec_client(client, dir, name); | 3160 | client = nfs4_create_sec_client(client, dir, name); |
3036 | if (IS_ERR(client)) | 3161 | if (IS_ERR(client)) |
3037 | return PTR_ERR(client); | 3162 | return PTR_ERR(client); |
@@ -3134,8 +3259,9 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
3134 | struct nfs4_exception exception = { }; | 3259 | struct nfs4_exception exception = { }; |
3135 | int err; | 3260 | int err; |
3136 | do { | 3261 | do { |
3137 | err = nfs4_handle_exception(NFS_SERVER(inode), | 3262 | err = _nfs4_proc_access(inode, entry); |
3138 | _nfs4_proc_access(inode, entry), | 3263 | trace_nfs4_access(inode, err); |
3264 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
3139 | &exception); | 3265 | &exception); |
3140 | } while (exception.retry); | 3266 | } while (exception.retry); |
3141 | return err; | 3267 | return err; |
@@ -3188,8 +3314,9 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
3188 | struct nfs4_exception exception = { }; | 3314 | struct nfs4_exception exception = { }; |
3189 | int err; | 3315 | int err; |
3190 | do { | 3316 | do { |
3191 | err = nfs4_handle_exception(NFS_SERVER(inode), | 3317 | err = _nfs4_proc_readlink(inode, page, pgbase, pglen); |
3192 | _nfs4_proc_readlink(inode, page, pgbase, pglen), | 3318 | trace_nfs4_readlink(inode, err); |
3319 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
3193 | &exception); | 3320 | &exception); |
3194 | } while (exception.retry); | 3321 | } while (exception.retry); |
3195 | return err; | 3322 | return err; |
@@ -3253,8 +3380,9 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
3253 | struct nfs4_exception exception = { }; | 3380 | struct nfs4_exception exception = { }; |
3254 | int err; | 3381 | int err; |
3255 | do { | 3382 | do { |
3256 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3383 | err = _nfs4_proc_remove(dir, name); |
3257 | _nfs4_proc_remove(dir, name), | 3384 | trace_nfs4_remove(dir, name, err); |
3385 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3258 | &exception); | 3386 | &exception); |
3259 | } while (exception.retry); | 3387 | } while (exception.retry); |
3260 | return err; | 3388 | return err; |
@@ -3268,7 +3396,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3268 | 3396 | ||
3269 | res->server = server; | 3397 | res->server = server; |
3270 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3398 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
3271 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3399 | nfs4_init_sequence(&args->seq_args, &res->seq_res, 1); |
3272 | 3400 | ||
3273 | nfs_fattr_init(res->dir_attr); | 3401 | nfs_fattr_init(res->dir_attr); |
3274 | } | 3402 | } |
@@ -3283,7 +3411,8 @@ static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlin | |||
3283 | 3411 | ||
3284 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 3412 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
3285 | { | 3413 | { |
3286 | struct nfs_removeres *res = task->tk_msg.rpc_resp; | 3414 | struct nfs_unlinkdata *data = task->tk_calldata; |
3415 | struct nfs_removeres *res = &data->res; | ||
3287 | 3416 | ||
3288 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3417 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3289 | return 0; | 3418 | return 0; |
@@ -3301,7 +3430,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
3301 | 3430 | ||
3302 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | 3431 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; |
3303 | res->server = server; | 3432 | res->server = server; |
3304 | nfs41_init_sequence(&arg->seq_args, &res->seq_res, 1); | 3433 | nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1); |
3305 | } | 3434 | } |
3306 | 3435 | ||
3307 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) | 3436 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) |
@@ -3315,7 +3444,8 @@ static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renam | |||
3315 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 3444 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
3316 | struct inode *new_dir) | 3445 | struct inode *new_dir) |
3317 | { | 3446 | { |
3318 | struct nfs_renameres *res = task->tk_msg.rpc_resp; | 3447 | struct nfs_renamedata *data = task->tk_calldata; |
3448 | struct nfs_renameres *res = &data->res; | ||
3319 | 3449 | ||
3320 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3450 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3321 | return 0; | 3451 | return 0; |
@@ -3361,9 +3491,10 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
3361 | struct nfs4_exception exception = { }; | 3491 | struct nfs4_exception exception = { }; |
3362 | int err; | 3492 | int err; |
3363 | do { | 3493 | do { |
3364 | err = nfs4_handle_exception(NFS_SERVER(old_dir), | 3494 | err = _nfs4_proc_rename(old_dir, old_name, |
3365 | _nfs4_proc_rename(old_dir, old_name, | 3495 | new_dir, new_name); |
3366 | new_dir, new_name), | 3496 | trace_nfs4_rename(old_dir, old_name, new_dir, new_name, err); |
3497 | err = nfs4_handle_exception(NFS_SERVER(old_dir), err, | ||
3367 | &exception); | 3498 | &exception); |
3368 | } while (exception.retry); | 3499 | } while (exception.retry); |
3369 | return err; | 3500 | return err; |
@@ -3525,9 +3656,9 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3525 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | 3656 | label = nfs4_label_init_security(dir, dentry, sattr, &l); |
3526 | 3657 | ||
3527 | do { | 3658 | do { |
3528 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3659 | err = _nfs4_proc_symlink(dir, dentry, page, len, sattr, label); |
3529 | _nfs4_proc_symlink(dir, dentry, page, | 3660 | trace_nfs4_symlink(dir, &dentry->d_name, err); |
3530 | len, sattr, label), | 3661 | err = nfs4_handle_exception(NFS_SERVER(dir), err, |
3531 | &exception); | 3662 | &exception); |
3532 | } while (exception.retry); | 3663 | } while (exception.retry); |
3533 | 3664 | ||
@@ -3564,8 +3695,9 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3564 | 3695 | ||
3565 | sattr->ia_mode &= ~current_umask(); | 3696 | sattr->ia_mode &= ~current_umask(); |
3566 | do { | 3697 | do { |
3567 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3698 | err = _nfs4_proc_mkdir(dir, dentry, sattr, label); |
3568 | _nfs4_proc_mkdir(dir, dentry, sattr, label), | 3699 | trace_nfs4_mkdir(dir, &dentry->d_name, err); |
3700 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3569 | &exception); | 3701 | &exception); |
3570 | } while (exception.retry); | 3702 | } while (exception.retry); |
3571 | nfs4_label_release_security(label); | 3703 | nfs4_label_release_security(label); |
@@ -3618,9 +3750,10 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3618 | struct nfs4_exception exception = { }; | 3750 | struct nfs4_exception exception = { }; |
3619 | int err; | 3751 | int err; |
3620 | do { | 3752 | do { |
3621 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), | 3753 | err = _nfs4_proc_readdir(dentry, cred, cookie, |
3622 | _nfs4_proc_readdir(dentry, cred, cookie, | 3754 | pages, count, plus); |
3623 | pages, count, plus), | 3755 | trace_nfs4_readdir(dentry->d_inode, err); |
3756 | err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), err, | ||
3624 | &exception); | 3757 | &exception); |
3625 | } while (exception.retry); | 3758 | } while (exception.retry); |
3626 | return err; | 3759 | return err; |
@@ -3672,8 +3805,9 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3672 | 3805 | ||
3673 | sattr->ia_mode &= ~current_umask(); | 3806 | sattr->ia_mode &= ~current_umask(); |
3674 | do { | 3807 | do { |
3675 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3808 | err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev); |
3676 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), | 3809 | trace_nfs4_mknod(dir, &dentry->d_name, err); |
3810 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
3677 | &exception); | 3811 | &exception); |
3678 | } while (exception.retry); | 3812 | } while (exception.retry); |
3679 | 3813 | ||
@@ -3741,6 +3875,7 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
3741 | 3875 | ||
3742 | do { | 3876 | do { |
3743 | err = _nfs4_do_fsinfo(server, fhandle, fsinfo); | 3877 | err = _nfs4_do_fsinfo(server, fhandle, fsinfo); |
3878 | trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err); | ||
3744 | if (err == 0) { | 3879 | if (err == 0) { |
3745 | struct nfs_client *clp = server->nfs_client; | 3880 | struct nfs_client *clp = server->nfs_client; |
3746 | 3881 | ||
@@ -3859,6 +3994,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) | |||
3859 | { | 3994 | { |
3860 | struct nfs_server *server = NFS_SERVER(data->header->inode); | 3995 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3861 | 3996 | ||
3997 | trace_nfs4_read(data, task->tk_status); | ||
3862 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3998 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3863 | rpc_restart_call_prepare(task); | 3999 | rpc_restart_call_prepare(task); |
3864 | return -EAGAIN; | 4000 | return -EAGAIN; |
@@ -3902,24 +4038,29 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3902 | data->timestamp = jiffies; | 4038 | data->timestamp = jiffies; |
3903 | data->read_done_cb = nfs4_read_done_cb; | 4039 | data->read_done_cb = nfs4_read_done_cb; |
3904 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 4040 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
3905 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | 4041 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); |
3906 | } | 4042 | } |
3907 | 4043 | ||
3908 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 4044 | static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3909 | { | 4045 | { |
3910 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 4046 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3911 | &data->args.seq_args, | 4047 | &data->args.seq_args, |
3912 | &data->res.seq_res, | 4048 | &data->res.seq_res, |
3913 | task)) | 4049 | task)) |
3914 | return; | 4050 | return 0; |
3915 | nfs4_set_rw_stateid(&data->args.stateid, data->args.context, | 4051 | if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context, |
3916 | data->args.lock_context, FMODE_READ); | 4052 | data->args.lock_context, FMODE_READ) == -EIO) |
4053 | return -EIO; | ||
4054 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | ||
4055 | return -EIO; | ||
4056 | return 0; | ||
3917 | } | 4057 | } |
3918 | 4058 | ||
3919 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 4059 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
3920 | { | 4060 | { |
3921 | struct inode *inode = data->header->inode; | 4061 | struct inode *inode = data->header->inode; |
3922 | 4062 | ||
4063 | trace_nfs4_write(data, task->tk_status); | ||
3923 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 4064 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3924 | rpc_restart_call_prepare(task); | 4065 | rpc_restart_call_prepare(task); |
3925 | return -EAGAIN; | 4066 | return -EAGAIN; |
@@ -3985,18 +4126,22 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3985 | data->timestamp = jiffies; | 4126 | data->timestamp = jiffies; |
3986 | 4127 | ||
3987 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; | 4128 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
3988 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4129 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
3989 | } | 4130 | } |
3990 | 4131 | ||
3991 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 4132 | static int nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3992 | { | 4133 | { |
3993 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 4134 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3994 | &data->args.seq_args, | 4135 | &data->args.seq_args, |
3995 | &data->res.seq_res, | 4136 | &data->res.seq_res, |
3996 | task)) | 4137 | task)) |
3997 | return; | 4138 | return 0; |
3998 | nfs4_set_rw_stateid(&data->args.stateid, data->args.context, | 4139 | if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context, |
3999 | data->args.lock_context, FMODE_WRITE); | 4140 | data->args.lock_context, FMODE_WRITE) == -EIO) |
4141 | return -EIO; | ||
4142 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | ||
4143 | return -EIO; | ||
4144 | return 0; | ||
4000 | } | 4145 | } |
4001 | 4146 | ||
4002 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 4147 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
@@ -4011,6 +4156,7 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *da | |||
4011 | { | 4156 | { |
4012 | struct inode *inode = data->inode; | 4157 | struct inode *inode = data->inode; |
4013 | 4158 | ||
4159 | trace_nfs4_commit(data, task->tk_status); | ||
4014 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 4160 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
4015 | rpc_restart_call_prepare(task); | 4161 | rpc_restart_call_prepare(task); |
4016 | return -EAGAIN; | 4162 | return -EAGAIN; |
@@ -4033,7 +4179,7 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess | |||
4033 | data->commit_done_cb = nfs4_commit_done_cb; | 4179 | data->commit_done_cb = nfs4_commit_done_cb; |
4034 | data->res.server = server; | 4180 | data->res.server = server; |
4035 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 4181 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
4036 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4182 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
4037 | } | 4183 | } |
4038 | 4184 | ||
4039 | struct nfs4_renewdata { | 4185 | struct nfs4_renewdata { |
@@ -4062,6 +4208,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) | |||
4062 | struct nfs_client *clp = data->client; | 4208 | struct nfs_client *clp = data->client; |
4063 | unsigned long timestamp = data->timestamp; | 4209 | unsigned long timestamp = data->timestamp; |
4064 | 4210 | ||
4211 | trace_nfs4_renew_async(clp, task->tk_status); | ||
4065 | if (task->tk_status < 0) { | 4212 | if (task->tk_status < 0) { |
4066 | /* Unless we're shutting down, schedule state recovery! */ | 4213 | /* Unless we're shutting down, schedule state recovery! */ |
4067 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) | 4214 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0) |
@@ -4319,6 +4466,7 @@ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bufl | |||
4319 | ssize_t ret; | 4466 | ssize_t ret; |
4320 | do { | 4467 | do { |
4321 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); | 4468 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); |
4469 | trace_nfs4_get_acl(inode, ret); | ||
4322 | if (ret >= 0) | 4470 | if (ret >= 0) |
4323 | break; | 4471 | break; |
4324 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); | 4472 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); |
@@ -4398,8 +4546,9 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
4398 | struct nfs4_exception exception = { }; | 4546 | struct nfs4_exception exception = { }; |
4399 | int err; | 4547 | int err; |
4400 | do { | 4548 | do { |
4401 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4549 | err = __nfs4_proc_set_acl(inode, buf, buflen); |
4402 | __nfs4_proc_set_acl(inode, buf, buflen), | 4550 | trace_nfs4_set_acl(inode, err); |
4551 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4403 | &exception); | 4552 | &exception); |
4404 | } while (exception.retry); | 4553 | } while (exception.retry); |
4405 | return err; | 4554 | return err; |
@@ -4452,8 +4601,9 @@ static int nfs4_get_security_label(struct inode *inode, void *buf, | |||
4452 | return -EOPNOTSUPP; | 4601 | return -EOPNOTSUPP; |
4453 | 4602 | ||
4454 | do { | 4603 | do { |
4455 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4604 | err = _nfs4_get_security_label(inode, buf, buflen); |
4456 | _nfs4_get_security_label(inode, buf, buflen), | 4605 | trace_nfs4_get_security_label(inode, err); |
4606 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4457 | &exception); | 4607 | &exception); |
4458 | } while (exception.retry); | 4608 | } while (exception.retry); |
4459 | return err; | 4609 | return err; |
@@ -4505,9 +4655,10 @@ static int nfs4_do_set_security_label(struct inode *inode, | |||
4505 | int err; | 4655 | int err; |
4506 | 4656 | ||
4507 | do { | 4657 | do { |
4508 | err = nfs4_handle_exception(NFS_SERVER(inode), | 4658 | err = _nfs4_do_set_security_label(inode, ilabel, |
4509 | _nfs4_do_set_security_label(inode, ilabel, | 4659 | fattr, olabel); |
4510 | fattr, olabel), | 4660 | trace_nfs4_set_security_label(inode, err); |
4661 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
4511 | &exception); | 4662 | &exception); |
4512 | } while (exception.retry); | 4663 | } while (exception.retry); |
4513 | return err; | 4664 | return err; |
@@ -4630,11 +4781,11 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, | |||
4630 | /* An impossible timestamp guarantees this value | 4781 | /* An impossible timestamp guarantees this value |
4631 | * will never match a generated boot time. */ | 4782 | * will never match a generated boot time. */ |
4632 | verf[0] = 0; | 4783 | verf[0] = 0; |
4633 | verf[1] = (__be32)(NSEC_PER_SEC + 1); | 4784 | verf[1] = cpu_to_be32(NSEC_PER_SEC + 1); |
4634 | } else { | 4785 | } else { |
4635 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); | 4786 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
4636 | verf[0] = (__be32)nn->boot_time.tv_sec; | 4787 | verf[0] = cpu_to_be32(nn->boot_time.tv_sec); |
4637 | verf[1] = (__be32)nn->boot_time.tv_nsec; | 4788 | verf[1] = cpu_to_be32(nn->boot_time.tv_nsec); |
4638 | } | 4789 | } |
4639 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | 4790 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); |
4640 | } | 4791 | } |
@@ -4660,10 +4811,14 @@ static unsigned int | |||
4660 | nfs4_init_uniform_client_string(const struct nfs_client *clp, | 4811 | nfs4_init_uniform_client_string(const struct nfs_client *clp, |
4661 | char *buf, size_t len) | 4812 | char *buf, size_t len) |
4662 | { | 4813 | { |
4663 | char *nodename = clp->cl_rpcclient->cl_nodename; | 4814 | const char *nodename = clp->cl_rpcclient->cl_nodename; |
4664 | 4815 | ||
4665 | if (nfs4_client_id_uniquifier[0] != '\0') | 4816 | if (nfs4_client_id_uniquifier[0] != '\0') |
4666 | nodename = nfs4_client_id_uniquifier; | 4817 | return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s", |
4818 | clp->rpc_ops->version, | ||
4819 | clp->cl_minorversion, | ||
4820 | nfs4_client_id_uniquifier, | ||
4821 | nodename); | ||
4667 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", | 4822 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", |
4668 | clp->rpc_ops->version, clp->cl_minorversion, | 4823 | clp->rpc_ops->version, clp->cl_minorversion, |
4669 | nodename); | 4824 | nodename); |
@@ -4724,6 +4879,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4724 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 4879 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4725 | setclientid.sc_name_len, setclientid.sc_name); | 4880 | setclientid.sc_name_len, setclientid.sc_name); |
4726 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4881 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4882 | trace_nfs4_setclientid(clp, status); | ||
4727 | dprintk("NFS reply setclientid: %d\n", status); | 4883 | dprintk("NFS reply setclientid: %d\n", status); |
4728 | return status; | 4884 | return status; |
4729 | } | 4885 | } |
@@ -4751,6 +4907,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
4751 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 4907 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4752 | clp->cl_clientid); | 4908 | clp->cl_clientid); |
4753 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4909 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4910 | trace_nfs4_setclientid_confirm(clp, status); | ||
4754 | dprintk("NFS reply setclientid_confirm: %d\n", status); | 4911 | dprintk("NFS reply setclientid_confirm: %d\n", status); |
4755 | return status; | 4912 | return status; |
4756 | } | 4913 | } |
@@ -4772,6 +4929,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
4772 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 4929 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
4773 | return; | 4930 | return; |
4774 | 4931 | ||
4932 | trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status); | ||
4775 | switch (task->tk_status) { | 4933 | switch (task->tk_status) { |
4776 | case -NFS4ERR_STALE_STATEID: | 4934 | case -NFS4ERR_STALE_STATEID: |
4777 | case -NFS4ERR_EXPIRED: | 4935 | case -NFS4ERR_EXPIRED: |
@@ -4793,7 +4951,6 @@ static void nfs4_delegreturn_release(void *calldata) | |||
4793 | kfree(calldata); | 4951 | kfree(calldata); |
4794 | } | 4952 | } |
4795 | 4953 | ||
4796 | #if defined(CONFIG_NFS_V4_1) | ||
4797 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | 4954 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) |
4798 | { | 4955 | { |
4799 | struct nfs4_delegreturndata *d_data; | 4956 | struct nfs4_delegreturndata *d_data; |
@@ -4805,12 +4962,9 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
4805 | &d_data->res.seq_res, | 4962 | &d_data->res.seq_res, |
4806 | task); | 4963 | task); |
4807 | } | 4964 | } |
4808 | #endif /* CONFIG_NFS_V4_1 */ | ||
4809 | 4965 | ||
4810 | static const struct rpc_call_ops nfs4_delegreturn_ops = { | 4966 | static const struct rpc_call_ops nfs4_delegreturn_ops = { |
4811 | #if defined(CONFIG_NFS_V4_1) | ||
4812 | .rpc_call_prepare = nfs4_delegreturn_prepare, | 4967 | .rpc_call_prepare = nfs4_delegreturn_prepare, |
4813 | #endif /* CONFIG_NFS_V4_1 */ | ||
4814 | .rpc_call_done = nfs4_delegreturn_done, | 4968 | .rpc_call_done = nfs4_delegreturn_done, |
4815 | .rpc_release = nfs4_delegreturn_release, | 4969 | .rpc_release = nfs4_delegreturn_release, |
4816 | }; | 4970 | }; |
@@ -4835,7 +4989,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
4835 | data = kzalloc(sizeof(*data), GFP_NOFS); | 4989 | data = kzalloc(sizeof(*data), GFP_NOFS); |
4836 | if (data == NULL) | 4990 | if (data == NULL) |
4837 | return -ENOMEM; | 4991 | return -ENOMEM; |
4838 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4992 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
4839 | data->args.fhandle = &data->fh; | 4993 | data->args.fhandle = &data->fh; |
4840 | data->args.stateid = &data->stateid; | 4994 | data->args.stateid = &data->stateid; |
4841 | data->args.bitmask = server->cache_consistency_bitmask; | 4995 | data->args.bitmask = server->cache_consistency_bitmask; |
@@ -4875,6 +5029,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 | |||
4875 | int err; | 5029 | int err; |
4876 | do { | 5030 | do { |
4877 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); | 5031 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); |
5032 | trace_nfs4_delegreturn(inode, err); | ||
4878 | switch (err) { | 5033 | switch (err) { |
4879 | case -NFS4ERR_STALE_STATEID: | 5034 | case -NFS4ERR_STALE_STATEID: |
4880 | case -NFS4ERR_EXPIRED: | 5035 | case -NFS4ERR_EXPIRED: |
@@ -4949,8 +5104,9 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
4949 | int err; | 5104 | int err; |
4950 | 5105 | ||
4951 | do { | 5106 | do { |
4952 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 5107 | err = _nfs4_proc_getlk(state, cmd, request); |
4953 | _nfs4_proc_getlk(state, cmd, request), | 5108 | trace_nfs4_get_lock(request, state, cmd, err); |
5109 | err = nfs4_handle_exception(NFS_SERVER(state->inode), err, | ||
4954 | &exception); | 5110 | &exception); |
4955 | } while (exception.retry); | 5111 | } while (exception.retry); |
4956 | return err; | 5112 | return err; |
@@ -5087,6 +5243,9 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
5087 | .flags = RPC_TASK_ASYNC, | 5243 | .flags = RPC_TASK_ASYNC, |
5088 | }; | 5244 | }; |
5089 | 5245 | ||
5246 | nfs4_state_protect(NFS_SERVER(lsp->ls_state->inode)->nfs_client, | ||
5247 | NFS_SP4_MACH_CRED_CLEANUP, &task_setup_data.rpc_client, &msg); | ||
5248 | |||
5090 | /* Ensure this is an unlock - when canceling a lock, the | 5249 | /* Ensure this is an unlock - when canceling a lock, the |
5091 | * canceled lock is passed in, and it won't be an unlock. | 5250 | * canceled lock is passed in, and it won't be an unlock. |
5092 | */ | 5251 | */ |
@@ -5098,7 +5257,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
5098 | return ERR_PTR(-ENOMEM); | 5257 | return ERR_PTR(-ENOMEM); |
5099 | } | 5258 | } |
5100 | 5259 | ||
5101 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 5260 | nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
5102 | msg.rpc_argp = &data->arg; | 5261 | msg.rpc_argp = &data->arg; |
5103 | msg.rpc_resp = &data->res; | 5262 | msg.rpc_resp = &data->res; |
5104 | task_setup_data.callback_data = data; | 5263 | task_setup_data.callback_data = data; |
@@ -5148,6 +5307,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
5148 | rpc_put_task(task); | 5307 | rpc_put_task(task); |
5149 | out: | 5308 | out: |
5150 | request->fl_flags = fl_flags; | 5309 | request->fl_flags = fl_flags; |
5310 | trace_nfs4_unlock(request, state, F_SETLK, status); | ||
5151 | return status; | 5311 | return status; |
5152 | } | 5312 | } |
5153 | 5313 | ||
@@ -5333,7 +5493,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
5333 | return -ENOMEM; | 5493 | return -ENOMEM; |
5334 | if (IS_SETLKW(cmd)) | 5494 | if (IS_SETLKW(cmd)) |
5335 | data->arg.block = 1; | 5495 | data->arg.block = 1; |
5336 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 5496 | nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
5337 | msg.rpc_argp = &data->arg; | 5497 | msg.rpc_argp = &data->arg; |
5338 | msg.rpc_resp = &data->res; | 5498 | msg.rpc_resp = &data->res; |
5339 | task_setup_data.callback_data = data; | 5499 | task_setup_data.callback_data = data; |
@@ -5371,6 +5531,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
5371 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 5531 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
5372 | return 0; | 5532 | return 0; |
5373 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); | 5533 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); |
5534 | trace_nfs4_lock_reclaim(request, state, F_SETLK, err); | ||
5374 | if (err != -NFS4ERR_DELAY) | 5535 | if (err != -NFS4ERR_DELAY) |
5375 | break; | 5536 | break; |
5376 | nfs4_handle_exception(server, err, &exception); | 5537 | nfs4_handle_exception(server, err, &exception); |
@@ -5389,10 +5550,15 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
5389 | err = nfs4_set_lock_state(state, request); | 5550 | err = nfs4_set_lock_state(state, request); |
5390 | if (err != 0) | 5551 | if (err != 0) |
5391 | return err; | 5552 | return err; |
5553 | if (!recover_lost_locks) { | ||
5554 | set_bit(NFS_LOCK_LOST, &request->fl_u.nfs4_fl.owner->ls_flags); | ||
5555 | return 0; | ||
5556 | } | ||
5392 | do { | 5557 | do { |
5393 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 5558 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
5394 | return 0; | 5559 | return 0; |
5395 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED); | 5560 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED); |
5561 | trace_nfs4_lock_expired(request, state, F_SETLK, err); | ||
5396 | switch (err) { | 5562 | switch (err) { |
5397 | default: | 5563 | default: |
5398 | goto out; | 5564 | goto out; |
@@ -5428,6 +5594,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
5428 | status = nfs41_test_stateid(server, | 5594 | status = nfs41_test_stateid(server, |
5429 | &lsp->ls_stateid, | 5595 | &lsp->ls_stateid, |
5430 | cred); | 5596 | cred); |
5597 | trace_nfs4_test_lock_stateid(state, lsp, status); | ||
5431 | if (status != NFS_OK) { | 5598 | if (status != NFS_OK) { |
5432 | /* Free the stateid unless the server | 5599 | /* Free the stateid unless the server |
5433 | * informs us the stateid is unrecognized. */ | 5600 | * informs us the stateid is unrecognized. */ |
@@ -5515,6 +5682,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
5515 | 5682 | ||
5516 | do { | 5683 | do { |
5517 | err = _nfs4_proc_setlk(state, cmd, request); | 5684 | err = _nfs4_proc_setlk(state, cmd, request); |
5685 | trace_nfs4_set_lock(request, state, cmd, err); | ||
5518 | if (err == -NFS4ERR_DENIED) | 5686 | if (err == -NFS4ERR_DENIED) |
5519 | err = -EAGAIN; | 5687 | err = -EAGAIN; |
5520 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 5688 | err = nfs4_handle_exception(NFS_SERVER(state->inode), |
@@ -5597,8 +5765,23 @@ struct nfs_release_lockowner_data { | |||
5597 | struct nfs4_lock_state *lsp; | 5765 | struct nfs4_lock_state *lsp; |
5598 | struct nfs_server *server; | 5766 | struct nfs_server *server; |
5599 | struct nfs_release_lockowner_args args; | 5767 | struct nfs_release_lockowner_args args; |
5768 | struct nfs4_sequence_args seq_args; | ||
5769 | struct nfs4_sequence_res seq_res; | ||
5600 | }; | 5770 | }; |
5601 | 5771 | ||
5772 | static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata) | ||
5773 | { | ||
5774 | struct nfs_release_lockowner_data *data = calldata; | ||
5775 | nfs40_setup_sequence(data->server, | ||
5776 | &data->seq_args, &data->seq_res, task); | ||
5777 | } | ||
5778 | |||
5779 | static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | ||
5780 | { | ||
5781 | struct nfs_release_lockowner_data *data = calldata; | ||
5782 | nfs40_sequence_done(task, &data->seq_res); | ||
5783 | } | ||
5784 | |||
5602 | static void nfs4_release_lockowner_release(void *calldata) | 5785 | static void nfs4_release_lockowner_release(void *calldata) |
5603 | { | 5786 | { |
5604 | struct nfs_release_lockowner_data *data = calldata; | 5787 | struct nfs_release_lockowner_data *data = calldata; |
@@ -5607,6 +5790,8 @@ static void nfs4_release_lockowner_release(void *calldata) | |||
5607 | } | 5790 | } |
5608 | 5791 | ||
5609 | static const struct rpc_call_ops nfs4_release_lockowner_ops = { | 5792 | static const struct rpc_call_ops nfs4_release_lockowner_ops = { |
5793 | .rpc_call_prepare = nfs4_release_lockowner_prepare, | ||
5794 | .rpc_call_done = nfs4_release_lockowner_done, | ||
5610 | .rpc_release = nfs4_release_lockowner_release, | 5795 | .rpc_release = nfs4_release_lockowner_release, |
5611 | }; | 5796 | }; |
5612 | 5797 | ||
@@ -5619,14 +5804,17 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
5619 | 5804 | ||
5620 | if (server->nfs_client->cl_mvops->minor_version != 0) | 5805 | if (server->nfs_client->cl_mvops->minor_version != 0) |
5621 | return -EINVAL; | 5806 | return -EINVAL; |
5807 | |||
5622 | data = kmalloc(sizeof(*data), GFP_NOFS); | 5808 | data = kmalloc(sizeof(*data), GFP_NOFS); |
5623 | if (!data) | 5809 | if (!data) |
5624 | return -ENOMEM; | 5810 | return -ENOMEM; |
5811 | nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); | ||
5625 | data->lsp = lsp; | 5812 | data->lsp = lsp; |
5626 | data->server = server; | 5813 | data->server = server; |
5627 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; | 5814 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
5628 | data->args.lock_owner.id = lsp->ls_seqid.owner_id; | 5815 | data->args.lock_owner.id = lsp->ls_seqid.owner_id; |
5629 | data->args.lock_owner.s_dev = server->s_dev; | 5816 | data->args.lock_owner.s_dev = server->s_dev; |
5817 | |||
5630 | msg.rpc_argp = &data->args; | 5818 | msg.rpc_argp = &data->args; |
5631 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); | 5819 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); |
5632 | return 0; | 5820 | return 0; |
@@ -5781,14 +5969,23 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5781 | struct nfs4_exception exception = { }; | 5969 | struct nfs4_exception exception = { }; |
5782 | int err; | 5970 | int err; |
5783 | do { | 5971 | do { |
5784 | err = nfs4_handle_exception(NFS_SERVER(dir), | 5972 | err = _nfs4_proc_fs_locations(client, dir, name, |
5785 | _nfs4_proc_fs_locations(client, dir, name, fs_locations, page), | 5973 | fs_locations, page); |
5974 | trace_nfs4_get_fs_locations(dir, name, err); | ||
5975 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
5786 | &exception); | 5976 | &exception); |
5787 | } while (exception.retry); | 5977 | } while (exception.retry); |
5788 | return err; | 5978 | return err; |
5789 | } | 5979 | } |
5790 | 5980 | ||
5791 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | 5981 | /** |
5982 | * If 'use_integrity' is true and the state managment nfs_client | ||
5983 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient | ||
5984 | * and the machine credential as per RFC3530bis and RFC5661 Security | ||
5985 | * Considerations sections. Otherwise, just use the user cred with the | ||
5986 | * filesystem's rpc_client. | ||
5987 | */ | ||
5988 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity) | ||
5792 | { | 5989 | { |
5793 | int status; | 5990 | int status; |
5794 | struct nfs4_secinfo_arg args = { | 5991 | struct nfs4_secinfo_arg args = { |
@@ -5803,10 +6000,25 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct | |||
5803 | .rpc_argp = &args, | 6000 | .rpc_argp = &args, |
5804 | .rpc_resp = &res, | 6001 | .rpc_resp = &res, |
5805 | }; | 6002 | }; |
6003 | struct rpc_clnt *clnt = NFS_SERVER(dir)->client; | ||
6004 | |||
6005 | if (use_integrity) { | ||
6006 | clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient; | ||
6007 | msg.rpc_cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client); | ||
6008 | } | ||
5806 | 6009 | ||
5807 | dprintk("NFS call secinfo %s\n", name->name); | 6010 | dprintk("NFS call secinfo %s\n", name->name); |
5808 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); | 6011 | |
6012 | nfs4_state_protect(NFS_SERVER(dir)->nfs_client, | ||
6013 | NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg); | ||
6014 | |||
6015 | status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, | ||
6016 | &res.seq_res, 0); | ||
5809 | dprintk("NFS reply secinfo: %d\n", status); | 6017 | dprintk("NFS reply secinfo: %d\n", status); |
6018 | |||
6019 | if (msg.rpc_cred) | ||
6020 | put_rpccred(msg.rpc_cred); | ||
6021 | |||
5810 | return status; | 6022 | return status; |
5811 | } | 6023 | } |
5812 | 6024 | ||
@@ -5816,8 +6028,23 @@ int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | |||
5816 | struct nfs4_exception exception = { }; | 6028 | struct nfs4_exception exception = { }; |
5817 | int err; | 6029 | int err; |
5818 | do { | 6030 | do { |
5819 | err = nfs4_handle_exception(NFS_SERVER(dir), | 6031 | err = -NFS4ERR_WRONGSEC; |
5820 | _nfs4_proc_secinfo(dir, name, flavors), | 6032 | |
6033 | /* try to use integrity protection with machine cred */ | ||
6034 | if (_nfs4_is_integrity_protected(NFS_SERVER(dir)->nfs_client)) | ||
6035 | err = _nfs4_proc_secinfo(dir, name, flavors, true); | ||
6036 | |||
6037 | /* | ||
6038 | * if unable to use integrity protection, or SECINFO with | ||
6039 | * integrity protection returns NFS4ERR_WRONGSEC (which is | ||
6040 | * disallowed by spec, but exists in deployed servers) use | ||
6041 | * the current filesystem's rpc_client and the user cred. | ||
6042 | */ | ||
6043 | if (err == -NFS4ERR_WRONGSEC) | ||
6044 | err = _nfs4_proc_secinfo(dir, name, flavors, false); | ||
6045 | |||
6046 | trace_nfs4_secinfo(dir, name, err); | ||
6047 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | ||
5821 | &exception); | 6048 | &exception); |
5822 | } while (exception.retry); | 6049 | } while (exception.retry); |
5823 | return err; | 6050 | return err; |
@@ -5881,6 +6108,7 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
5881 | } | 6108 | } |
5882 | 6109 | ||
5883 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6110 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6111 | trace_nfs4_bind_conn_to_session(clp, status); | ||
5884 | if (status == 0) { | 6112 | if (status == 0) { |
5885 | if (memcmp(res.session->sess_id.data, | 6113 | if (memcmp(res.session->sess_id.data, |
5886 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { | 6114 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { |
@@ -5909,16 +6137,124 @@ out: | |||
5909 | } | 6137 | } |
5910 | 6138 | ||
5911 | /* | 6139 | /* |
5912 | * nfs4_proc_exchange_id() | 6140 | * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map |
6141 | * and operations we'd like to see to enable certain features in the allow map | ||
6142 | */ | ||
6143 | static const struct nfs41_state_protection nfs4_sp4_mach_cred_request = { | ||
6144 | .how = SP4_MACH_CRED, | ||
6145 | .enforce.u.words = { | ||
6146 | [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) | | ||
6147 | 1 << (OP_EXCHANGE_ID - 32) | | ||
6148 | 1 << (OP_CREATE_SESSION - 32) | | ||
6149 | 1 << (OP_DESTROY_SESSION - 32) | | ||
6150 | 1 << (OP_DESTROY_CLIENTID - 32) | ||
6151 | }, | ||
6152 | .allow.u.words = { | ||
6153 | [0] = 1 << (OP_CLOSE) | | ||
6154 | 1 << (OP_LOCKU), | ||
6155 | [1] = 1 << (OP_SECINFO - 32) | | ||
6156 | 1 << (OP_SECINFO_NO_NAME - 32) | | ||
6157 | 1 << (OP_TEST_STATEID - 32) | | ||
6158 | 1 << (OP_FREE_STATEID - 32) | ||
6159 | } | ||
6160 | }; | ||
6161 | |||
6162 | /* | ||
6163 | * Select the state protection mode for client `clp' given the server results | ||
6164 | * from exchange_id in `sp'. | ||
5913 | * | 6165 | * |
5914 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | 6166 | * Returns 0 on success, negative errno otherwise. |
6167 | */ | ||
6168 | static int nfs4_sp4_select_mode(struct nfs_client *clp, | ||
6169 | struct nfs41_state_protection *sp) | ||
6170 | { | ||
6171 | static const u32 supported_enforce[NFS4_OP_MAP_NUM_WORDS] = { | ||
6172 | [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) | | ||
6173 | 1 << (OP_EXCHANGE_ID - 32) | | ||
6174 | 1 << (OP_CREATE_SESSION - 32) | | ||
6175 | 1 << (OP_DESTROY_SESSION - 32) | | ||
6176 | 1 << (OP_DESTROY_CLIENTID - 32) | ||
6177 | }; | ||
6178 | unsigned int i; | ||
6179 | |||
6180 | if (sp->how == SP4_MACH_CRED) { | ||
6181 | /* Print state protect result */ | ||
6182 | dfprintk(MOUNT, "Server SP4_MACH_CRED support:\n"); | ||
6183 | for (i = 0; i <= LAST_NFS4_OP; i++) { | ||
6184 | if (test_bit(i, sp->enforce.u.longs)) | ||
6185 | dfprintk(MOUNT, " enforce op %d\n", i); | ||
6186 | if (test_bit(i, sp->allow.u.longs)) | ||
6187 | dfprintk(MOUNT, " allow op %d\n", i); | ||
6188 | } | ||
6189 | |||
6190 | /* make sure nothing is on enforce list that isn't supported */ | ||
6191 | for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) { | ||
6192 | if (sp->enforce.u.words[i] & ~supported_enforce[i]) { | ||
6193 | dfprintk(MOUNT, "sp4_mach_cred: disabled\n"); | ||
6194 | return -EINVAL; | ||
6195 | } | ||
6196 | } | ||
6197 | |||
6198 | /* | ||
6199 | * Minimal mode - state operations are allowed to use machine | ||
6200 | * credential. Note this already happens by default, so the | ||
6201 | * client doesn't have to do anything more than the negotiation. | ||
6202 | * | ||
6203 | * NOTE: we don't care if EXCHANGE_ID is in the list - | ||
6204 | * we're already using the machine cred for exchange_id | ||
6205 | * and will never use a different cred. | ||
6206 | */ | ||
6207 | if (test_bit(OP_BIND_CONN_TO_SESSION, sp->enforce.u.longs) && | ||
6208 | test_bit(OP_CREATE_SESSION, sp->enforce.u.longs) && | ||
6209 | test_bit(OP_DESTROY_SESSION, sp->enforce.u.longs) && | ||
6210 | test_bit(OP_DESTROY_CLIENTID, sp->enforce.u.longs)) { | ||
6211 | dfprintk(MOUNT, "sp4_mach_cred:\n"); | ||
6212 | dfprintk(MOUNT, " minimal mode enabled\n"); | ||
6213 | set_bit(NFS_SP4_MACH_CRED_MINIMAL, &clp->cl_sp4_flags); | ||
6214 | } else { | ||
6215 | dfprintk(MOUNT, "sp4_mach_cred: disabled\n"); | ||
6216 | return -EINVAL; | ||
6217 | } | ||
6218 | |||
6219 | if (test_bit(OP_CLOSE, sp->allow.u.longs) && | ||
6220 | test_bit(OP_LOCKU, sp->allow.u.longs)) { | ||
6221 | dfprintk(MOUNT, " cleanup mode enabled\n"); | ||
6222 | set_bit(NFS_SP4_MACH_CRED_CLEANUP, &clp->cl_sp4_flags); | ||
6223 | } | ||
6224 | |||
6225 | if (test_bit(OP_SECINFO, sp->allow.u.longs) && | ||
6226 | test_bit(OP_SECINFO_NO_NAME, sp->allow.u.longs)) { | ||
6227 | dfprintk(MOUNT, " secinfo mode enabled\n"); | ||
6228 | set_bit(NFS_SP4_MACH_CRED_SECINFO, &clp->cl_sp4_flags); | ||
6229 | } | ||
6230 | |||
6231 | if (test_bit(OP_TEST_STATEID, sp->allow.u.longs) && | ||
6232 | test_bit(OP_FREE_STATEID, sp->allow.u.longs)) { | ||
6233 | dfprintk(MOUNT, " stateid mode enabled\n"); | ||
6234 | set_bit(NFS_SP4_MACH_CRED_STATEID, &clp->cl_sp4_flags); | ||
6235 | } | ||
6236 | |||
6237 | if (test_bit(OP_WRITE, sp->allow.u.longs)) { | ||
6238 | dfprintk(MOUNT, " write mode enabled\n"); | ||
6239 | set_bit(NFS_SP4_MACH_CRED_WRITE, &clp->cl_sp4_flags); | ||
6240 | } | ||
6241 | |||
6242 | if (test_bit(OP_COMMIT, sp->allow.u.longs)) { | ||
6243 | dfprintk(MOUNT, " commit mode enabled\n"); | ||
6244 | set_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags); | ||
6245 | } | ||
6246 | } | ||
6247 | |||
6248 | return 0; | ||
6249 | } | ||
6250 | |||
6251 | /* | ||
6252 | * _nfs4_proc_exchange_id() | ||
5915 | * | 6253 | * |
5916 | * Since the clientid has expired, all compounds using sessions | 6254 | * Wrapper for EXCHANGE_ID operation. |
5917 | * associated with the stale clientid will be returning | ||
5918 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
5919 | * be in some phase of session reset. | ||
5920 | */ | 6255 | */ |
5921 | int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | 6256 | static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, |
6257 | u32 sp4_how) | ||
5922 | { | 6258 | { |
5923 | nfs4_verifier verifier; | 6259 | nfs4_verifier verifier; |
5924 | struct nfs41_exchange_id_args args = { | 6260 | struct nfs41_exchange_id_args args = { |
@@ -5965,10 +6301,30 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5965 | goto out_server_scope; | 6301 | goto out_server_scope; |
5966 | } | 6302 | } |
5967 | 6303 | ||
6304 | switch (sp4_how) { | ||
6305 | case SP4_NONE: | ||
6306 | args.state_protect.how = SP4_NONE; | ||
6307 | break; | ||
6308 | |||
6309 | case SP4_MACH_CRED: | ||
6310 | args.state_protect = nfs4_sp4_mach_cred_request; | ||
6311 | break; | ||
6312 | |||
6313 | default: | ||
6314 | /* unsupported! */ | ||
6315 | WARN_ON_ONCE(1); | ||
6316 | status = -EINVAL; | ||
6317 | goto out_server_scope; | ||
6318 | } | ||
6319 | |||
5968 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6320 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6321 | trace_nfs4_exchange_id(clp, status); | ||
5969 | if (status == 0) | 6322 | if (status == 0) |
5970 | status = nfs4_check_cl_exchange_flags(res.flags); | 6323 | status = nfs4_check_cl_exchange_flags(res.flags); |
5971 | 6324 | ||
6325 | if (status == 0) | ||
6326 | status = nfs4_sp4_select_mode(clp, &res.state_protect); | ||
6327 | |||
5972 | if (status == 0) { | 6328 | if (status == 0) { |
5973 | clp->cl_clientid = res.clientid; | 6329 | clp->cl_clientid = res.clientid; |
5974 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | 6330 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); |
@@ -6015,6 +6371,35 @@ out: | |||
6015 | return status; | 6371 | return status; |
6016 | } | 6372 | } |
6017 | 6373 | ||
6374 | /* | ||
6375 | * nfs4_proc_exchange_id() | ||
6376 | * | ||
6377 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | ||
6378 | * | ||
6379 | * Since the clientid has expired, all compounds using sessions | ||
6380 | * associated with the stale clientid will be returning | ||
6381 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | ||
6382 | * be in some phase of session reset. | ||
6383 | * | ||
6384 | * Will attempt to negotiate SP4_MACH_CRED if krb5i / krb5p auth is used. | ||
6385 | */ | ||
6386 | int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | ||
6387 | { | ||
6388 | rpc_authflavor_t authflavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
6389 | int status; | ||
6390 | |||
6391 | /* try SP4_MACH_CRED if krb5i/p */ | ||
6392 | if (authflavor == RPC_AUTH_GSS_KRB5I || | ||
6393 | authflavor == RPC_AUTH_GSS_KRB5P) { | ||
6394 | status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED); | ||
6395 | if (!status) | ||
6396 | return 0; | ||
6397 | } | ||
6398 | |||
6399 | /* try SP4_NONE */ | ||
6400 | return _nfs4_proc_exchange_id(clp, cred, SP4_NONE); | ||
6401 | } | ||
6402 | |||
6018 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | 6403 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, |
6019 | struct rpc_cred *cred) | 6404 | struct rpc_cred *cred) |
6020 | { | 6405 | { |
@@ -6026,6 +6411,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | |||
6026 | int status; | 6411 | int status; |
6027 | 6412 | ||
6028 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6413 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6414 | trace_nfs4_destroy_clientid(clp, status); | ||
6029 | if (status) | 6415 | if (status) |
6030 | dprintk("NFS: Got error %d from the server %s on " | 6416 | dprintk("NFS: Got error %d from the server %s on " |
6031 | "DESTROY_CLIENTID.", status, clp->cl_hostname); | 6417 | "DESTROY_CLIENTID.", status, clp->cl_hostname); |
@@ -6063,7 +6449,7 @@ int nfs4_destroy_clientid(struct nfs_client *clp) | |||
6063 | goto out; | 6449 | goto out; |
6064 | if (clp->cl_preserve_clid) | 6450 | if (clp->cl_preserve_clid) |
6065 | goto out; | 6451 | goto out; |
6066 | cred = nfs4_get_exchange_id_cred(clp); | 6452 | cred = nfs4_get_clid_cred(clp); |
6067 | ret = nfs4_proc_destroy_clientid(clp, cred); | 6453 | ret = nfs4_proc_destroy_clientid(clp, cred); |
6068 | if (cred) | 6454 | if (cred) |
6069 | put_rpccred(cred); | 6455 | put_rpccred(cred); |
@@ -6155,7 +6541,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
6155 | }; | 6541 | }; |
6156 | int status; | 6542 | int status; |
6157 | 6543 | ||
6158 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); | 6544 | nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); |
6159 | nfs4_set_sequence_privileged(&args.la_seq_args); | 6545 | nfs4_set_sequence_privileged(&args.la_seq_args); |
6160 | dprintk("--> %s\n", __func__); | 6546 | dprintk("--> %s\n", __func__); |
6161 | task = rpc_run_task(&task_setup); | 6547 | task = rpc_run_task(&task_setup); |
@@ -6289,6 +6675,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, | |||
6289 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | 6675 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); |
6290 | 6676 | ||
6291 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6677 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6678 | trace_nfs4_create_session(clp, status); | ||
6292 | 6679 | ||
6293 | if (!status) { | 6680 | if (!status) { |
6294 | /* Verify the session's negotiated channel_attrs values */ | 6681 | /* Verify the session's negotiated channel_attrs values */ |
@@ -6352,6 +6739,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
6352 | return status; | 6739 | return status; |
6353 | 6740 | ||
6354 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6741 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6742 | trace_nfs4_destroy_session(session->clp, status); | ||
6355 | 6743 | ||
6356 | if (status) | 6744 | if (status) |
6357 | dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " | 6745 | dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " |
@@ -6401,6 +6789,7 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data) | |||
6401 | if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp)) | 6789 | if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp)) |
6402 | return; | 6790 | return; |
6403 | 6791 | ||
6792 | trace_nfs4_sequence(clp, task->tk_status); | ||
6404 | if (task->tk_status < 0) { | 6793 | if (task->tk_status < 0) { |
6405 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | 6794 | dprintk("%s ERROR %d\n", __func__, task->tk_status); |
6406 | if (atomic_read(&clp->cl_count) == 1) | 6795 | if (atomic_read(&clp->cl_count) == 1) |
@@ -6458,7 +6847,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, | |||
6458 | nfs_put_client(clp); | 6847 | nfs_put_client(clp); |
6459 | return ERR_PTR(-ENOMEM); | 6848 | return ERR_PTR(-ENOMEM); |
6460 | } | 6849 | } |
6461 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); | 6850 | nfs4_init_sequence(&calldata->args, &calldata->res, 0); |
6462 | if (is_privileged) | 6851 | if (is_privileged) |
6463 | nfs4_set_sequence_privileged(&calldata->args); | 6852 | nfs4_set_sequence_privileged(&calldata->args); |
6464 | msg.rpc_argp = &calldata->args; | 6853 | msg.rpc_argp = &calldata->args; |
@@ -6553,6 +6942,7 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) | |||
6553 | if (!nfs41_sequence_done(task, res)) | 6942 | if (!nfs41_sequence_done(task, res)) |
6554 | return; | 6943 | return; |
6555 | 6944 | ||
6945 | trace_nfs4_reclaim_complete(clp, task->tk_status); | ||
6556 | if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { | 6946 | if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { |
6557 | rpc_restart_call_prepare(task); | 6947 | rpc_restart_call_prepare(task); |
6558 | return; | 6948 | return; |
@@ -6600,7 +6990,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp, | |||
6600 | calldata->clp = clp; | 6990 | calldata->clp = clp; |
6601 | calldata->arg.one_fs = 0; | 6991 | calldata->arg.one_fs = 0; |
6602 | 6992 | ||
6603 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); | 6993 | nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); |
6604 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); | 6994 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); |
6605 | msg.rpc_argp = &calldata->arg; | 6995 | msg.rpc_argp = &calldata->arg; |
6606 | msg.rpc_resp = &calldata->res; | 6996 | msg.rpc_resp = &calldata->res; |
@@ -6791,7 +7181,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6791 | 7181 | ||
6792 | lgp->res.layoutp = &lgp->args.layout; | 7182 | lgp->res.layoutp = &lgp->args.layout; |
6793 | lgp->res.seq_res.sr_slot = NULL; | 7183 | lgp->res.seq_res.sr_slot = NULL; |
6794 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 7184 | nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6795 | 7185 | ||
6796 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ | 7186 | /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ |
6797 | pnfs_get_layout_hdr(NFS_I(inode)->layout); | 7187 | pnfs_get_layout_hdr(NFS_I(inode)->layout); |
@@ -6802,6 +7192,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6802 | status = nfs4_wait_for_completion_rpc_task(task); | 7192 | status = nfs4_wait_for_completion_rpc_task(task); |
6803 | if (status == 0) | 7193 | if (status == 0) |
6804 | status = task->tk_status; | 7194 | status = task->tk_status; |
7195 | trace_nfs4_layoutget(lgp->args.ctx, | ||
7196 | &lgp->args.range, | ||
7197 | &lgp->res.range, | ||
7198 | status); | ||
6805 | /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ | 7199 | /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ |
6806 | if (status == 0 && lgp->res.layoutp->len) | 7200 | if (status == 0 && lgp->res.layoutp->len) |
6807 | lseg = pnfs_layout_process(lgp); | 7201 | lseg = pnfs_layout_process(lgp); |
@@ -6874,7 +7268,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6874 | .rpc_cred = lrp->cred, | 7268 | .rpc_cred = lrp->cred, |
6875 | }; | 7269 | }; |
6876 | struct rpc_task_setup task_setup_data = { | 7270 | struct rpc_task_setup task_setup_data = { |
6877 | .rpc_client = lrp->clp->cl_rpcclient, | 7271 | .rpc_client = NFS_SERVER(lrp->args.inode)->client, |
6878 | .rpc_message = &msg, | 7272 | .rpc_message = &msg, |
6879 | .callback_ops = &nfs4_layoutreturn_call_ops, | 7273 | .callback_ops = &nfs4_layoutreturn_call_ops, |
6880 | .callback_data = lrp, | 7274 | .callback_data = lrp, |
@@ -6882,11 +7276,12 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
6882 | int status; | 7276 | int status; |
6883 | 7277 | ||
6884 | dprintk("--> %s\n", __func__); | 7278 | dprintk("--> %s\n", __func__); |
6885 | nfs41_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); | 7279 | nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); |
6886 | task = rpc_run_task(&task_setup_data); | 7280 | task = rpc_run_task(&task_setup_data); |
6887 | if (IS_ERR(task)) | 7281 | if (IS_ERR(task)) |
6888 | return PTR_ERR(task); | 7282 | return PTR_ERR(task); |
6889 | status = task->tk_status; | 7283 | status = task->tk_status; |
7284 | trace_nfs4_layoutreturn(lrp->args.inode, status); | ||
6890 | dprintk("<-- %s status=%d\n", __func__, status); | 7285 | dprintk("<-- %s status=%d\n", __func__, status); |
6891 | rpc_put_task(task); | 7286 | rpc_put_task(task); |
6892 | return status; | 7287 | return status; |
@@ -7063,7 +7458,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
7063 | data->args.lastbytewritten, | 7458 | data->args.lastbytewritten, |
7064 | data->args.inode->i_ino); | 7459 | data->args.inode->i_ino); |
7065 | 7460 | ||
7066 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 7461 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
7067 | task = rpc_run_task(&task_setup_data); | 7462 | task = rpc_run_task(&task_setup_data); |
7068 | if (IS_ERR(task)) | 7463 | if (IS_ERR(task)) |
7069 | return PTR_ERR(task); | 7464 | return PTR_ERR(task); |
@@ -7073,15 +7468,21 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
7073 | if (status != 0) | 7468 | if (status != 0) |
7074 | goto out; | 7469 | goto out; |
7075 | status = task->tk_status; | 7470 | status = task->tk_status; |
7471 | trace_nfs4_layoutcommit(data->args.inode, status); | ||
7076 | out: | 7472 | out: |
7077 | dprintk("%s: status %d\n", __func__, status); | 7473 | dprintk("%s: status %d\n", __func__, status); |
7078 | rpc_put_task(task); | 7474 | rpc_put_task(task); |
7079 | return status; | 7475 | return status; |
7080 | } | 7476 | } |
7081 | 7477 | ||
7478 | /** | ||
7479 | * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if | ||
7480 | * possible) as per RFC3530bis and RFC5661 Security Considerations sections | ||
7481 | */ | ||
7082 | static int | 7482 | static int |
7083 | _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | 7483 | _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, |
7084 | struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) | 7484 | struct nfs_fsinfo *info, |
7485 | struct nfs4_secinfo_flavors *flavors, bool use_integrity) | ||
7085 | { | 7486 | { |
7086 | struct nfs41_secinfo_no_name_args args = { | 7487 | struct nfs41_secinfo_no_name_args args = { |
7087 | .style = SECINFO_STYLE_CURRENT_FH, | 7488 | .style = SECINFO_STYLE_CURRENT_FH, |
@@ -7094,7 +7495,23 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7094 | .rpc_argp = &args, | 7495 | .rpc_argp = &args, |
7095 | .rpc_resp = &res, | 7496 | .rpc_resp = &res, |
7096 | }; | 7497 | }; |
7097 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 7498 | struct rpc_clnt *clnt = server->client; |
7499 | int status; | ||
7500 | |||
7501 | if (use_integrity) { | ||
7502 | clnt = server->nfs_client->cl_rpcclient; | ||
7503 | msg.rpc_cred = nfs4_get_clid_cred(server->nfs_client); | ||
7504 | } | ||
7505 | |||
7506 | dprintk("--> %s\n", __func__); | ||
7507 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, | ||
7508 | &res.seq_res, 0); | ||
7509 | dprintk("<-- %s status=%d\n", __func__, status); | ||
7510 | |||
7511 | if (msg.rpc_cred) | ||
7512 | put_rpccred(msg.rpc_cred); | ||
7513 | |||
7514 | return status; | ||
7098 | } | 7515 | } |
7099 | 7516 | ||
7100 | static int | 7517 | static int |
@@ -7104,7 +7521,24 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7104 | struct nfs4_exception exception = { }; | 7521 | struct nfs4_exception exception = { }; |
7105 | int err; | 7522 | int err; |
7106 | do { | 7523 | do { |
7107 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); | 7524 | /* first try using integrity protection */ |
7525 | err = -NFS4ERR_WRONGSEC; | ||
7526 | |||
7527 | /* try to use integrity protection with machine cred */ | ||
7528 | if (_nfs4_is_integrity_protected(server->nfs_client)) | ||
7529 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, | ||
7530 | flavors, true); | ||
7531 | |||
7532 | /* | ||
7533 | * if unable to use integrity protection, or SECINFO with | ||
7534 | * integrity protection returns NFS4ERR_WRONGSEC (which is | ||
7535 | * disallowed by spec, but exists in deployed servers) use | ||
7536 | * the current filesystem's rpc_client and the user cred. | ||
7537 | */ | ||
7538 | if (err == -NFS4ERR_WRONGSEC) | ||
7539 | err = _nfs41_proc_secinfo_no_name(server, fhandle, info, | ||
7540 | flavors, false); | ||
7541 | |||
7108 | switch (err) { | 7542 | switch (err) { |
7109 | case 0: | 7543 | case 0: |
7110 | case -NFS4ERR_WRONGSEC: | 7544 | case -NFS4ERR_WRONGSEC: |
@@ -7174,11 +7608,15 @@ static int _nfs41_test_stateid(struct nfs_server *server, | |||
7174 | .rpc_resp = &res, | 7608 | .rpc_resp = &res, |
7175 | .rpc_cred = cred, | 7609 | .rpc_cred = cred, |
7176 | }; | 7610 | }; |
7611 | struct rpc_clnt *rpc_client = server->client; | ||
7612 | |||
7613 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID, | ||
7614 | &rpc_client, &msg); | ||
7177 | 7615 | ||
7178 | dprintk("NFS call test_stateid %p\n", stateid); | 7616 | dprintk("NFS call test_stateid %p\n", stateid); |
7179 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 7617 | nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); |
7180 | nfs4_set_sequence_privileged(&args.seq_args); | 7618 | nfs4_set_sequence_privileged(&args.seq_args); |
7181 | status = nfs4_call_sync_sequence(server->client, server, &msg, | 7619 | status = nfs4_call_sync_sequence(rpc_client, server, &msg, |
7182 | &args.seq_args, &res.seq_res); | 7620 | &args.seq_args, &res.seq_res); |
7183 | if (status != NFS_OK) { | 7621 | if (status != NFS_OK) { |
7184 | dprintk("NFS reply test_stateid: failed, %d\n", status); | 7622 | dprintk("NFS reply test_stateid: failed, %d\n", status); |
@@ -7247,7 +7685,7 @@ static void nfs41_free_stateid_release(void *calldata) | |||
7247 | kfree(calldata); | 7685 | kfree(calldata); |
7248 | } | 7686 | } |
7249 | 7687 | ||
7250 | const struct rpc_call_ops nfs41_free_stateid_ops = { | 7688 | static const struct rpc_call_ops nfs41_free_stateid_ops = { |
7251 | .rpc_call_prepare = nfs41_free_stateid_prepare, | 7689 | .rpc_call_prepare = nfs41_free_stateid_prepare, |
7252 | .rpc_call_done = nfs41_free_stateid_done, | 7690 | .rpc_call_done = nfs41_free_stateid_done, |
7253 | .rpc_release = nfs41_free_stateid_release, | 7691 | .rpc_release = nfs41_free_stateid_release, |
@@ -7270,6 +7708,9 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
7270 | }; | 7708 | }; |
7271 | struct nfs_free_stateid_data *data; | 7709 | struct nfs_free_stateid_data *data; |
7272 | 7710 | ||
7711 | nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID, | ||
7712 | &task_setup.rpc_client, &msg); | ||
7713 | |||
7273 | dprintk("NFS call free_stateid %p\n", stateid); | 7714 | dprintk("NFS call free_stateid %p\n", stateid); |
7274 | data = kmalloc(sizeof(*data), GFP_NOFS); | 7715 | data = kmalloc(sizeof(*data), GFP_NOFS); |
7275 | if (!data) | 7716 | if (!data) |
@@ -7281,7 +7722,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, | |||
7281 | 7722 | ||
7282 | msg.rpc_argp = &data->args; | 7723 | msg.rpc_argp = &data->args; |
7283 | msg.rpc_resp = &data->res; | 7724 | msg.rpc_resp = &data->res; |
7284 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | 7725 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); |
7285 | if (privileged) | 7726 | if (privileged) |
7286 | nfs4_set_sequence_privileged(&data->args.seq_args); | 7727 | nfs4_set_sequence_privileged(&data->args.seq_args); |
7287 | 7728 | ||
@@ -7357,7 +7798,6 @@ static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | |||
7357 | .recover_open = nfs4_open_reclaim, | 7798 | .recover_open = nfs4_open_reclaim, |
7358 | .recover_lock = nfs4_lock_reclaim, | 7799 | .recover_lock = nfs4_lock_reclaim, |
7359 | .establish_clid = nfs4_init_clientid, | 7800 | .establish_clid = nfs4_init_clientid, |
7360 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
7361 | .detect_trunking = nfs40_discover_server_trunking, | 7801 | .detect_trunking = nfs40_discover_server_trunking, |
7362 | }; | 7802 | }; |
7363 | 7803 | ||
@@ -7368,7 +7808,6 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | |||
7368 | .recover_open = nfs4_open_reclaim, | 7808 | .recover_open = nfs4_open_reclaim, |
7369 | .recover_lock = nfs4_lock_reclaim, | 7809 | .recover_lock = nfs4_lock_reclaim, |
7370 | .establish_clid = nfs41_init_clientid, | 7810 | .establish_clid = nfs41_init_clientid, |
7371 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
7372 | .reclaim_complete = nfs41_proc_reclaim_complete, | 7811 | .reclaim_complete = nfs41_proc_reclaim_complete, |
7373 | .detect_trunking = nfs41_discover_server_trunking, | 7812 | .detect_trunking = nfs41_discover_server_trunking, |
7374 | }; | 7813 | }; |
@@ -7380,7 +7819,6 @@ static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { | |||
7380 | .recover_open = nfs4_open_expired, | 7819 | .recover_open = nfs4_open_expired, |
7381 | .recover_lock = nfs4_lock_expired, | 7820 | .recover_lock = nfs4_lock_expired, |
7382 | .establish_clid = nfs4_init_clientid, | 7821 | .establish_clid = nfs4_init_clientid, |
7383 | .get_clid_cred = nfs4_get_setclientid_cred, | ||
7384 | }; | 7822 | }; |
7385 | 7823 | ||
7386 | #if defined(CONFIG_NFS_V4_1) | 7824 | #if defined(CONFIG_NFS_V4_1) |
@@ -7390,7 +7828,6 @@ static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = { | |||
7390 | .recover_open = nfs41_open_expired, | 7828 | .recover_open = nfs41_open_expired, |
7391 | .recover_lock = nfs41_lock_expired, | 7829 | .recover_lock = nfs41_lock_expired, |
7392 | .establish_clid = nfs41_init_clientid, | 7830 | .establish_clid = nfs41_init_clientid, |
7393 | .get_clid_cred = nfs4_get_exchange_id_cred, | ||
7394 | }; | 7831 | }; |
7395 | #endif /* CONFIG_NFS_V4_1 */ | 7832 | #endif /* CONFIG_NFS_V4_1 */ |
7396 | 7833 | ||
@@ -7414,10 +7851,12 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
7414 | | NFS_CAP_ATOMIC_OPEN | 7851 | | NFS_CAP_ATOMIC_OPEN |
7415 | | NFS_CAP_CHANGE_ATTR | 7852 | | NFS_CAP_CHANGE_ATTR |
7416 | | NFS_CAP_POSIX_LOCK, | 7853 | | NFS_CAP_POSIX_LOCK, |
7417 | .call_sync = _nfs4_call_sync, | 7854 | .init_client = nfs40_init_client, |
7855 | .shutdown_client = nfs40_shutdown_client, | ||
7418 | .match_stateid = nfs4_match_stateid, | 7856 | .match_stateid = nfs4_match_stateid, |
7419 | .find_root_sec = nfs4_find_root_sec, | 7857 | .find_root_sec = nfs4_find_root_sec, |
7420 | .free_lock_state = nfs4_release_lockowner, | 7858 | .free_lock_state = nfs4_release_lockowner, |
7859 | .call_sync_ops = &nfs40_call_sync_ops, | ||
7421 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, | 7860 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
7422 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, | 7861 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
7423 | .state_renewal_ops = &nfs40_state_renewal_ops, | 7862 | .state_renewal_ops = &nfs40_state_renewal_ops, |
@@ -7432,10 +7871,12 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
7432 | | NFS_CAP_POSIX_LOCK | 7871 | | NFS_CAP_POSIX_LOCK |
7433 | | NFS_CAP_STATEID_NFSV41 | 7872 | | NFS_CAP_STATEID_NFSV41 |
7434 | | NFS_CAP_ATOMIC_OPEN_V1, | 7873 | | NFS_CAP_ATOMIC_OPEN_V1, |
7435 | .call_sync = nfs4_call_sync_sequence, | 7874 | .init_client = nfs41_init_client, |
7875 | .shutdown_client = nfs41_shutdown_client, | ||
7436 | .match_stateid = nfs41_match_stateid, | 7876 | .match_stateid = nfs41_match_stateid, |
7437 | .find_root_sec = nfs41_find_root_sec, | 7877 | .find_root_sec = nfs41_find_root_sec, |
7438 | .free_lock_state = nfs41_free_lock_state, | 7878 | .free_lock_state = nfs41_free_lock_state, |
7879 | .call_sync_ops = &nfs41_call_sync_ops, | ||
7439 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 7880 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
7440 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 7881 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
7441 | .state_renewal_ops = &nfs41_state_renewal_ops, | 7882 | .state_renewal_ops = &nfs41_state_renewal_ops, |
@@ -7451,10 +7892,12 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
7451 | | NFS_CAP_POSIX_LOCK | 7892 | | NFS_CAP_POSIX_LOCK |
7452 | | NFS_CAP_STATEID_NFSV41 | 7893 | | NFS_CAP_STATEID_NFSV41 |
7453 | | NFS_CAP_ATOMIC_OPEN_V1, | 7894 | | NFS_CAP_ATOMIC_OPEN_V1, |
7454 | .call_sync = nfs4_call_sync_sequence, | 7895 | .init_client = nfs41_init_client, |
7896 | .shutdown_client = nfs41_shutdown_client, | ||
7455 | .match_stateid = nfs41_match_stateid, | 7897 | .match_stateid = nfs41_match_stateid, |
7456 | .find_root_sec = nfs41_find_root_sec, | 7898 | .find_root_sec = nfs41_find_root_sec, |
7457 | .free_lock_state = nfs41_free_lock_state, | 7899 | .free_lock_state = nfs41_free_lock_state, |
7900 | .call_sync_ops = &nfs41_call_sync_ops, | ||
7458 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 7901 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
7459 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 7902 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
7460 | .state_renewal_ops = &nfs41_state_renewal_ops, | 7903 | .state_renewal_ops = &nfs41_state_renewal_ops, |
@@ -7471,7 +7914,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | |||
7471 | #endif | 7914 | #endif |
7472 | }; | 7915 | }; |
7473 | 7916 | ||
7474 | const struct inode_operations nfs4_dir_inode_operations = { | 7917 | static const struct inode_operations nfs4_dir_inode_operations = { |
7475 | .create = nfs_create, | 7918 | .create = nfs_create, |
7476 | .lookup = nfs_lookup, | 7919 | .lookup = nfs_lookup, |
7477 | .atomic_open = nfs_atomic_open, | 7920 | .atomic_open = nfs_atomic_open, |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index 36e21cb29d65..cf883c7ae053 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -23,6 +23,14 @@ | |||
23 | 23 | ||
24 | #define NFSDBG_FACILITY NFSDBG_STATE | 24 | #define NFSDBG_FACILITY NFSDBG_STATE |
25 | 25 | ||
26 | static void nfs4_init_slot_table(struct nfs4_slot_table *tbl, const char *queue) | ||
27 | { | ||
28 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
29 | spin_lock_init(&tbl->slot_tbl_lock); | ||
30 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, queue); | ||
31 | init_completion(&tbl->complete); | ||
32 | } | ||
33 | |||
26 | /* | 34 | /* |
27 | * nfs4_shrink_slot_table - free retired slots from the slot table | 35 | * nfs4_shrink_slot_table - free retired slots from the slot table |
28 | */ | 36 | */ |
@@ -44,6 +52,17 @@ static void nfs4_shrink_slot_table(struct nfs4_slot_table *tbl, u32 newsize) | |||
44 | } | 52 | } |
45 | } | 53 | } |
46 | 54 | ||
55 | /** | ||
56 | * nfs4_slot_tbl_drain_complete - wake waiters when drain is complete | ||
57 | * @tbl - controlling slot table | ||
58 | * | ||
59 | */ | ||
60 | void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl) | ||
61 | { | ||
62 | if (nfs4_slot_tbl_draining(tbl)) | ||
63 | complete(&tbl->complete); | ||
64 | } | ||
65 | |||
47 | /* | 66 | /* |
48 | * nfs4_free_slot - free a slot and efficiently update slot table. | 67 | * nfs4_free_slot - free a slot and efficiently update slot table. |
49 | * | 68 | * |
@@ -76,7 +95,7 @@ void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot) | |||
76 | nfs4_slot_tbl_drain_complete(tbl); | 95 | nfs4_slot_tbl_drain_complete(tbl); |
77 | } | 96 | } |
78 | } | 97 | } |
79 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, | 98 | dprintk("%s: slotid %u highest_used_slotid %u\n", __func__, |
80 | slotid, tbl->highest_used_slotid); | 99 | slotid, tbl->highest_used_slotid); |
81 | } | 100 | } |
82 | 101 | ||
@@ -146,9 +165,9 @@ struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl) | |||
146 | ret->generation = tbl->generation; | 165 | ret->generation = tbl->generation; |
147 | 166 | ||
148 | out: | 167 | out: |
149 | dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", | 168 | dprintk("<-- %s used_slots=%04lx highest_used=%u slotid=%u\n", |
150 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | 169 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, |
151 | !IS_ERR(ret) ? ret->slot_nr : -1); | 170 | !IS_ERR(ret) ? ret->slot_nr : NFS4_NO_SLOT); |
152 | return ret; | 171 | return ret; |
153 | } | 172 | } |
154 | 173 | ||
@@ -191,7 +210,7 @@ static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, | |||
191 | { | 210 | { |
192 | int ret; | 211 | int ret; |
193 | 212 | ||
194 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | 213 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %u\n", __func__, |
195 | max_reqs, tbl->max_slots); | 214 | max_reqs, tbl->max_slots); |
196 | 215 | ||
197 | if (max_reqs > NFS4_MAX_SLOT_TABLE) | 216 | if (max_reqs > NFS4_MAX_SLOT_TABLE) |
@@ -205,18 +224,36 @@ static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, | |||
205 | nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue); | 224 | nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue); |
206 | spin_unlock(&tbl->slot_tbl_lock); | 225 | spin_unlock(&tbl->slot_tbl_lock); |
207 | 226 | ||
208 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | 227 | dprintk("%s: tbl=%p slots=%p max_slots=%u\n", __func__, |
209 | tbl, tbl->slots, tbl->max_slots); | 228 | tbl, tbl->slots, tbl->max_slots); |
210 | out: | 229 | out: |
211 | dprintk("<-- %s: return %d\n", __func__, ret); | 230 | dprintk("<-- %s: return %d\n", __func__, ret); |
212 | return ret; | 231 | return ret; |
213 | } | 232 | } |
214 | 233 | ||
215 | /* Destroy the slot table */ | 234 | /** |
216 | static void nfs4_destroy_slot_tables(struct nfs4_session *session) | 235 | * nfs4_release_slot_table - release resources attached to a slot table |
236 | * @tbl: slot table to shut down | ||
237 | * | ||
238 | */ | ||
239 | void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | ||
240 | { | ||
241 | nfs4_shrink_slot_table(tbl, 0); | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * nfs4_setup_slot_table - prepare a stand-alone slot table for use | ||
246 | * @tbl: slot table to set up | ||
247 | * @max_reqs: maximum number of requests allowed | ||
248 | * @queue: name to give RPC wait queue | ||
249 | * | ||
250 | * Returns zero on success, or a negative errno. | ||
251 | */ | ||
252 | int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, unsigned int max_reqs, | ||
253 | const char *queue) | ||
217 | { | 254 | { |
218 | nfs4_shrink_slot_table(&session->fc_slot_table, 0); | 255 | nfs4_init_slot_table(tbl, queue); |
219 | nfs4_shrink_slot_table(&session->bc_slot_table, 0); | 256 | return nfs4_realloc_slot_table(tbl, max_reqs, 0); |
220 | } | 257 | } |
221 | 258 | ||
222 | static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) | 259 | static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) |
@@ -273,6 +310,8 @@ void nfs41_wake_slot_table(struct nfs4_slot_table *tbl) | |||
273 | } | 310 | } |
274 | } | 311 | } |
275 | 312 | ||
313 | #if defined(CONFIG_NFS_V4_1) | ||
314 | |||
276 | static void nfs41_set_max_slotid_locked(struct nfs4_slot_table *tbl, | 315 | static void nfs41_set_max_slotid_locked(struct nfs4_slot_table *tbl, |
277 | u32 target_highest_slotid) | 316 | u32 target_highest_slotid) |
278 | { | 317 | { |
@@ -383,6 +422,12 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | |||
383 | spin_unlock(&tbl->slot_tbl_lock); | 422 | spin_unlock(&tbl->slot_tbl_lock); |
384 | } | 423 | } |
385 | 424 | ||
425 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | ||
426 | { | ||
427 | nfs4_release_slot_table(&session->fc_slot_table); | ||
428 | nfs4_release_slot_table(&session->bc_slot_table); | ||
429 | } | ||
430 | |||
386 | /* | 431 | /* |
387 | * Initialize or reset the forechannel and backchannel tables | 432 | * Initialize or reset the forechannel and backchannel tables |
388 | */ | 433 | */ |
@@ -405,31 +450,20 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
405 | if (status && tbl->slots == NULL) | 450 | if (status && tbl->slots == NULL) |
406 | /* Fore and back channel share a connection so get | 451 | /* Fore and back channel share a connection so get |
407 | * both slot tables or neither */ | 452 | * both slot tables or neither */ |
408 | nfs4_destroy_slot_tables(ses); | 453 | nfs4_destroy_session_slot_tables(ses); |
409 | return status; | 454 | return status; |
410 | } | 455 | } |
411 | 456 | ||
412 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | 457 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) |
413 | { | 458 | { |
414 | struct nfs4_session *session; | 459 | struct nfs4_session *session; |
415 | struct nfs4_slot_table *tbl; | ||
416 | 460 | ||
417 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | 461 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); |
418 | if (!session) | 462 | if (!session) |
419 | return NULL; | 463 | return NULL; |
420 | 464 | ||
421 | tbl = &session->fc_slot_table; | 465 | nfs4_init_slot_table(&session->fc_slot_table, "ForeChannel Slot table"); |
422 | tbl->highest_used_slotid = NFS4_NO_SLOT; | 466 | nfs4_init_slot_table(&session->bc_slot_table, "BackChannel Slot table"); |
423 | spin_lock_init(&tbl->slot_tbl_lock); | ||
424 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | ||
425 | init_completion(&tbl->complete); | ||
426 | |||
427 | tbl = &session->bc_slot_table; | ||
428 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
429 | spin_lock_init(&tbl->slot_tbl_lock); | ||
430 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | ||
431 | init_completion(&tbl->complete); | ||
432 | |||
433 | session->session_state = 1<<NFS4_SESSION_INITING; | 467 | session->session_state = 1<<NFS4_SESSION_INITING; |
434 | 468 | ||
435 | session->clp = clp; | 469 | session->clp = clp; |
@@ -441,7 +475,7 @@ void nfs4_destroy_session(struct nfs4_session *session) | |||
441 | struct rpc_xprt *xprt; | 475 | struct rpc_xprt *xprt; |
442 | struct rpc_cred *cred; | 476 | struct rpc_cred *cred; |
443 | 477 | ||
444 | cred = nfs4_get_exchange_id_cred(session->clp); | 478 | cred = nfs4_get_clid_cred(session->clp); |
445 | nfs4_proc_destroy_session(session, cred); | 479 | nfs4_proc_destroy_session(session, cred); |
446 | if (cred) | 480 | if (cred) |
447 | put_rpccred(cred); | 481 | put_rpccred(cred); |
@@ -452,7 +486,7 @@ void nfs4_destroy_session(struct nfs4_session *session) | |||
452 | dprintk("%s Destroy backchannel for xprt %p\n", | 486 | dprintk("%s Destroy backchannel for xprt %p\n", |
453 | __func__, xprt); | 487 | __func__, xprt); |
454 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); | 488 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); |
455 | nfs4_destroy_slot_tables(session); | 489 | nfs4_destroy_session_slot_tables(session); |
456 | kfree(session); | 490 | kfree(session); |
457 | } | 491 | } |
458 | 492 | ||
@@ -513,4 +547,4 @@ int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) | |||
513 | } | 547 | } |
514 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | 548 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); |
515 | 549 | ||
516 | 550 | #endif /* defined(CONFIG_NFS_V4_1) */ | |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 3a153d82b90c..232306100651 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #define __LINUX_FS_NFS_NFS4SESSION_H | 8 | #define __LINUX_FS_NFS_NFS4SESSION_H |
9 | 9 | ||
10 | /* maximum number of slots to use */ | 10 | /* maximum number of slots to use */ |
11 | #define NFS4_DEF_SLOT_TABLE_SIZE (16U) | 11 | #define NFS4_DEF_SLOT_TABLE_SIZE (64U) |
12 | #define NFS4_MAX_SLOT_TABLE (1024U) | 12 | #define NFS4_MAX_SLOT_TABLE (1024U) |
13 | #define NFS4_NO_SLOT ((u32)-1) | 13 | #define NFS4_NO_SLOT ((u32)-1) |
14 | 14 | ||
@@ -72,10 +72,22 @@ enum nfs4_session_state { | |||
72 | NFS4_SESSION_INITING, | 72 | NFS4_SESSION_INITING, |
73 | }; | 73 | }; |
74 | 74 | ||
75 | #if defined(CONFIG_NFS_V4_1) | 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
76 | unsigned int max_reqs, const char *queue); | ||
77 | extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl); | ||
76 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); |
77 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); |
80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | ||
81 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
82 | struct nfs4_slot *slot); | ||
83 | void nfs41_wake_slot_table(struct nfs4_slot_table *tbl); | ||
84 | |||
85 | static inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl) | ||
86 | { | ||
87 | return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); | ||
88 | } | ||
78 | 89 | ||
90 | #if defined(CONFIG_NFS_V4_1) | ||
79 | extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, | 91 | extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, |
80 | u32 target_highest_slotid); | 92 | u32 target_highest_slotid); |
81 | extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | 93 | extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, |
@@ -89,17 +101,6 @@ extern void nfs4_destroy_session(struct nfs4_session *session); | |||
89 | extern int nfs4_init_session(struct nfs_client *clp); | 101 | extern int nfs4_init_session(struct nfs_client *clp); |
90 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); | 102 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); |
91 | 103 | ||
92 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | ||
93 | |||
94 | static inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl) | ||
95 | { | ||
96 | return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); | ||
97 | } | ||
98 | |||
99 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
100 | struct nfs4_slot *slot); | ||
101 | void nfs41_wake_slot_table(struct nfs4_slot_table *tbl); | ||
102 | |||
103 | /* | 104 | /* |
104 | * Determine if sessions are in use. | 105 | * Determine if sessions are in use. |
105 | */ | 106 | */ |
@@ -117,6 +118,16 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | |||
117 | return 0; | 118 | return 0; |
118 | } | 119 | } |
119 | 120 | ||
121 | #ifdef CONFIG_CRC32 | ||
122 | /* | ||
123 | * nfs_session_id_hash - calculate the crc32 hash for the session id | ||
124 | * @session - pointer to session | ||
125 | */ | ||
126 | #define nfs_session_id_hash(sess_id) \ | ||
127 | (~crc32_le(0xFFFFFFFF, &(sess_id)->data[0], sizeof((sess_id)->data))) | ||
128 | #else | ||
129 | #define nfs_session_id_hash(session) (0) | ||
130 | #endif | ||
120 | #else /* defined(CONFIG_NFS_V4_1) */ | 131 | #else /* defined(CONFIG_NFS_V4_1) */ |
121 | 132 | ||
122 | static inline int nfs4_init_session(struct nfs_client *clp) | 133 | static inline int nfs4_init_session(struct nfs_client *clp) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e22862f13564..cc14cbb78b73 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -154,6 +154,19 @@ struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp) | |||
154 | return cred; | 154 | return cred; |
155 | } | 155 | } |
156 | 156 | ||
157 | static void nfs4_root_machine_cred(struct nfs_client *clp) | ||
158 | { | ||
159 | struct rpc_cred *cred, *new; | ||
160 | |||
161 | new = rpc_lookup_machine_cred(NULL); | ||
162 | spin_lock(&clp->cl_lock); | ||
163 | cred = clp->cl_machine_cred; | ||
164 | clp->cl_machine_cred = new; | ||
165 | spin_unlock(&clp->cl_lock); | ||
166 | if (cred != NULL) | ||
167 | put_rpccred(cred); | ||
168 | } | ||
169 | |||
157 | static struct rpc_cred * | 170 | static struct rpc_cred * |
158 | nfs4_get_renew_cred_server_locked(struct nfs_server *server) | 171 | nfs4_get_renew_cred_server_locked(struct nfs_server *server) |
159 | { | 172 | { |
@@ -202,32 +215,6 @@ out: | |||
202 | return cred; | 215 | return cred; |
203 | } | 216 | } |
204 | 217 | ||
205 | #if defined(CONFIG_NFS_V4_1) | ||
206 | |||
207 | static int nfs41_setup_state_renewal(struct nfs_client *clp) | ||
208 | { | ||
209 | int status; | ||
210 | struct nfs_fsinfo fsinfo; | ||
211 | |||
212 | if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) { | ||
213 | nfs4_schedule_state_renewal(clp); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | status = nfs4_proc_get_lease_time(clp, &fsinfo); | ||
218 | if (status == 0) { | ||
219 | /* Update lease time and schedule renewal */ | ||
220 | spin_lock(&clp->cl_lock); | ||
221 | clp->cl_lease_time = fsinfo.lease_time * HZ; | ||
222 | clp->cl_last_renewal = jiffies; | ||
223 | spin_unlock(&clp->cl_lock); | ||
224 | |||
225 | nfs4_schedule_state_renewal(clp); | ||
226 | } | ||
227 | |||
228 | return status; | ||
229 | } | ||
230 | |||
231 | static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl) | 218 | static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl) |
232 | { | 219 | { |
233 | if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { | 220 | if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { |
@@ -241,20 +228,18 @@ static void nfs4_end_drain_session(struct nfs_client *clp) | |||
241 | { | 228 | { |
242 | struct nfs4_session *ses = clp->cl_session; | 229 | struct nfs4_session *ses = clp->cl_session; |
243 | 230 | ||
231 | if (clp->cl_slot_tbl) { | ||
232 | nfs4_end_drain_slot_table(clp->cl_slot_tbl); | ||
233 | return; | ||
234 | } | ||
235 | |||
244 | if (ses != NULL) { | 236 | if (ses != NULL) { |
245 | nfs4_end_drain_slot_table(&ses->bc_slot_table); | 237 | nfs4_end_drain_slot_table(&ses->bc_slot_table); |
246 | nfs4_end_drain_slot_table(&ses->fc_slot_table); | 238 | nfs4_end_drain_slot_table(&ses->fc_slot_table); |
247 | } | 239 | } |
248 | } | 240 | } |
249 | 241 | ||
250 | /* | 242 | #if defined(CONFIG_NFS_V4_1) |
251 | * Signal state manager thread if session fore channel is drained | ||
252 | */ | ||
253 | void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl) | ||
254 | { | ||
255 | if (nfs4_slot_tbl_draining(tbl)) | ||
256 | complete(&tbl->complete); | ||
257 | } | ||
258 | 243 | ||
259 | static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl) | 244 | static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl) |
260 | { | 245 | { |
@@ -274,6 +259,9 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) | |||
274 | struct nfs4_session *ses = clp->cl_session; | 259 | struct nfs4_session *ses = clp->cl_session; |
275 | int ret = 0; | 260 | int ret = 0; |
276 | 261 | ||
262 | if (clp->cl_slot_tbl) | ||
263 | return nfs4_drain_slot_tbl(clp->cl_slot_tbl); | ||
264 | |||
277 | /* back channel */ | 265 | /* back channel */ |
278 | ret = nfs4_drain_slot_tbl(&ses->bc_slot_table); | 266 | ret = nfs4_drain_slot_tbl(&ses->bc_slot_table); |
279 | if (ret) | 267 | if (ret) |
@@ -282,6 +270,30 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) | |||
282 | return nfs4_drain_slot_tbl(&ses->fc_slot_table); | 270 | return nfs4_drain_slot_tbl(&ses->fc_slot_table); |
283 | } | 271 | } |
284 | 272 | ||
273 | static int nfs41_setup_state_renewal(struct nfs_client *clp) | ||
274 | { | ||
275 | int status; | ||
276 | struct nfs_fsinfo fsinfo; | ||
277 | |||
278 | if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) { | ||
279 | nfs4_schedule_state_renewal(clp); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | status = nfs4_proc_get_lease_time(clp, &fsinfo); | ||
284 | if (status == 0) { | ||
285 | /* Update lease time and schedule renewal */ | ||
286 | spin_lock(&clp->cl_lock); | ||
287 | clp->cl_lease_time = fsinfo.lease_time * HZ; | ||
288 | clp->cl_last_renewal = jiffies; | ||
289 | spin_unlock(&clp->cl_lock); | ||
290 | |||
291 | nfs4_schedule_state_renewal(clp); | ||
292 | } | ||
293 | |||
294 | return status; | ||
295 | } | ||
296 | |||
285 | static void nfs41_finish_session_reset(struct nfs_client *clp) | 297 | static void nfs41_finish_session_reset(struct nfs_client *clp) |
286 | { | 298 | { |
287 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 299 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
@@ -339,62 +351,21 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, | |||
339 | return nfs41_walk_client_list(clp, result, cred); | 351 | return nfs41_walk_client_list(clp, result, cred); |
340 | } | 352 | } |
341 | 353 | ||
342 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp) | ||
343 | { | ||
344 | struct rpc_cred *cred; | ||
345 | |||
346 | spin_lock(&clp->cl_lock); | ||
347 | cred = nfs4_get_machine_cred_locked(clp); | ||
348 | spin_unlock(&clp->cl_lock); | ||
349 | return cred; | ||
350 | } | ||
351 | |||
352 | #endif /* CONFIG_NFS_V4_1 */ | 354 | #endif /* CONFIG_NFS_V4_1 */ |
353 | 355 | ||
354 | static struct rpc_cred * | ||
355 | nfs4_get_setclientid_cred_server(struct nfs_server *server) | ||
356 | { | ||
357 | struct nfs_client *clp = server->nfs_client; | ||
358 | struct rpc_cred *cred = NULL; | ||
359 | struct nfs4_state_owner *sp; | ||
360 | struct rb_node *pos; | ||
361 | |||
362 | spin_lock(&clp->cl_lock); | ||
363 | pos = rb_first(&server->state_owners); | ||
364 | if (pos != NULL) { | ||
365 | sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); | ||
366 | cred = get_rpccred(sp->so_cred); | ||
367 | } | ||
368 | spin_unlock(&clp->cl_lock); | ||
369 | return cred; | ||
370 | } | ||
371 | |||
372 | /** | 356 | /** |
373 | * nfs4_get_setclientid_cred - Acquire credential for a setclientid operation | 357 | * nfs4_get_clid_cred - Acquire credential for a setclientid operation |
374 | * @clp: client state handle | 358 | * @clp: client state handle |
375 | * | 359 | * |
376 | * Returns an rpc_cred with reference count bumped, or NULL. | 360 | * Returns an rpc_cred with reference count bumped, or NULL. |
377 | */ | 361 | */ |
378 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) | 362 | struct rpc_cred *nfs4_get_clid_cred(struct nfs_client *clp) |
379 | { | 363 | { |
380 | struct nfs_server *server; | ||
381 | struct rpc_cred *cred; | 364 | struct rpc_cred *cred; |
382 | 365 | ||
383 | spin_lock(&clp->cl_lock); | 366 | spin_lock(&clp->cl_lock); |
384 | cred = nfs4_get_machine_cred_locked(clp); | 367 | cred = nfs4_get_machine_cred_locked(clp); |
385 | spin_unlock(&clp->cl_lock); | 368 | spin_unlock(&clp->cl_lock); |
386 | if (cred != NULL) | ||
387 | goto out; | ||
388 | |||
389 | rcu_read_lock(); | ||
390 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | ||
391 | cred = nfs4_get_setclientid_cred_server(server); | ||
392 | if (cred != NULL) | ||
393 | break; | ||
394 | } | ||
395 | rcu_read_unlock(); | ||
396 | |||
397 | out: | ||
398 | return cred; | 369 | return cred; |
399 | } | 370 | } |
400 | 371 | ||
@@ -998,7 +969,9 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, | |||
998 | fl_pid = lockowner->l_pid; | 969 | fl_pid = lockowner->l_pid; |
999 | spin_lock(&state->state_lock); | 970 | spin_lock(&state->state_lock); |
1000 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); | 971 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
1001 | if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { | 972 | if (lsp && test_bit(NFS_LOCK_LOST, &lsp->ls_flags)) |
973 | ret = -EIO; | ||
974 | else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { | ||
1002 | nfs4_stateid_copy(dst, &lsp->ls_stateid); | 975 | nfs4_stateid_copy(dst, &lsp->ls_stateid); |
1003 | ret = 0; | 976 | ret = 0; |
1004 | smp_rmb(); | 977 | smp_rmb(); |
@@ -1038,11 +1011,17 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | |||
1038 | int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, | 1011 | int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, |
1039 | fmode_t fmode, const struct nfs_lockowner *lockowner) | 1012 | fmode_t fmode, const struct nfs_lockowner *lockowner) |
1040 | { | 1013 | { |
1041 | int ret = 0; | 1014 | int ret = nfs4_copy_lock_stateid(dst, state, lockowner); |
1015 | if (ret == -EIO) | ||
1016 | /* A lost lock - don't even consider delegations */ | ||
1017 | goto out; | ||
1042 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) | 1018 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) |
1043 | goto out; | 1019 | goto out; |
1044 | ret = nfs4_copy_lock_stateid(dst, state, lockowner); | ||
1045 | if (ret != -ENOENT) | 1020 | if (ret != -ENOENT) |
1021 | /* nfs4_copy_delegation_stateid() didn't over-write | ||
1022 | * dst, so it still has the lock stateid which we now | ||
1023 | * choose to use. | ||
1024 | */ | ||
1046 | goto out; | 1025 | goto out; |
1047 | ret = nfs4_copy_open_stateid(dst, state); | 1026 | ret = nfs4_copy_open_stateid(dst, state); |
1048 | out: | 1027 | out: |
@@ -1443,14 +1422,16 @@ restart: | |||
1443 | if (status >= 0) { | 1422 | if (status >= 0) { |
1444 | status = nfs4_reclaim_locks(state, ops); | 1423 | status = nfs4_reclaim_locks(state, ops); |
1445 | if (status >= 0) { | 1424 | if (status >= 0) { |
1446 | spin_lock(&state->state_lock); | 1425 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) { |
1447 | list_for_each_entry(lock, &state->lock_states, ls_locks) { | 1426 | spin_lock(&state->state_lock); |
1448 | if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags)) | 1427 | list_for_each_entry(lock, &state->lock_states, ls_locks) { |
1449 | pr_warn_ratelimited("NFS: " | 1428 | if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags)) |
1450 | "%s: Lock reclaim " | 1429 | pr_warn_ratelimited("NFS: " |
1451 | "failed!\n", __func__); | 1430 | "%s: Lock reclaim " |
1431 | "failed!\n", __func__); | ||
1432 | } | ||
1433 | spin_unlock(&state->state_lock); | ||
1452 | } | 1434 | } |
1453 | spin_unlock(&state->state_lock); | ||
1454 | nfs4_put_open_state(state); | 1435 | nfs4_put_open_state(state); |
1455 | spin_lock(&sp->so_lock); | 1436 | spin_lock(&sp->so_lock); |
1456 | goto restart; | 1437 | goto restart; |
@@ -1618,7 +1599,7 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | |||
1618 | if (!nfs4_state_clear_reclaim_reboot(clp)) | 1599 | if (!nfs4_state_clear_reclaim_reboot(clp)) |
1619 | return; | 1600 | return; |
1620 | ops = clp->cl_mvops->reboot_recovery_ops; | 1601 | ops = clp->cl_mvops->reboot_recovery_ops; |
1621 | cred = ops->get_clid_cred(clp); | 1602 | cred = nfs4_get_clid_cred(clp); |
1622 | nfs4_reclaim_complete(clp, ops, cred); | 1603 | nfs4_reclaim_complete(clp, ops, cred); |
1623 | put_rpccred(cred); | 1604 | put_rpccred(cred); |
1624 | } | 1605 | } |
@@ -1732,7 +1713,7 @@ static int nfs4_check_lease(struct nfs_client *clp) | |||
1732 | cred = ops->get_state_renewal_cred_locked(clp); | 1713 | cred = ops->get_state_renewal_cred_locked(clp); |
1733 | spin_unlock(&clp->cl_lock); | 1714 | spin_unlock(&clp->cl_lock); |
1734 | if (cred == NULL) { | 1715 | if (cred == NULL) { |
1735 | cred = nfs4_get_setclientid_cred(clp); | 1716 | cred = nfs4_get_clid_cred(clp); |
1736 | status = -ENOKEY; | 1717 | status = -ENOKEY; |
1737 | if (cred == NULL) | 1718 | if (cred == NULL) |
1738 | goto out; | 1719 | goto out; |
@@ -1804,7 +1785,7 @@ static int nfs4_establish_lease(struct nfs_client *clp) | |||
1804 | clp->cl_mvops->reboot_recovery_ops; | 1785 | clp->cl_mvops->reboot_recovery_ops; |
1805 | int status; | 1786 | int status; |
1806 | 1787 | ||
1807 | cred = ops->get_clid_cred(clp); | 1788 | cred = nfs4_get_clid_cred(clp); |
1808 | if (cred == NULL) | 1789 | if (cred == NULL) |
1809 | return -ENOENT; | 1790 | return -ENOENT; |
1810 | status = ops->establish_clid(clp, cred); | 1791 | status = ops->establish_clid(clp, cred); |
@@ -1878,7 +1859,7 @@ int nfs4_discover_server_trunking(struct nfs_client *clp, | |||
1878 | mutex_lock(&nfs_clid_init_mutex); | 1859 | mutex_lock(&nfs_clid_init_mutex); |
1879 | again: | 1860 | again: |
1880 | status = -ENOENT; | 1861 | status = -ENOENT; |
1881 | cred = ops->get_clid_cred(clp); | 1862 | cred = nfs4_get_clid_cred(clp); |
1882 | if (cred == NULL) | 1863 | if (cred == NULL) |
1883 | goto out_unlock; | 1864 | goto out_unlock; |
1884 | 1865 | ||
@@ -1896,7 +1877,11 @@ again: | |||
1896 | __func__, status); | 1877 | __func__, status); |
1897 | goto again; | 1878 | goto again; |
1898 | case -EACCES: | 1879 | case -EACCES: |
1899 | if (i++) | 1880 | if (i++ == 0) { |
1881 | nfs4_root_machine_cred(clp); | ||
1882 | goto again; | ||
1883 | } | ||
1884 | if (i > 2) | ||
1900 | break; | 1885 | break; |
1901 | case -NFS4ERR_CLID_INUSE: | 1886 | case -NFS4ERR_CLID_INUSE: |
1902 | case -NFS4ERR_WRONGSEC: | 1887 | case -NFS4ERR_WRONGSEC: |
@@ -2052,7 +2037,7 @@ static int nfs4_reset_session(struct nfs_client *clp) | |||
2052 | if (!nfs4_has_session(clp)) | 2037 | if (!nfs4_has_session(clp)) |
2053 | return 0; | 2038 | return 0; |
2054 | nfs4_begin_drain_session(clp); | 2039 | nfs4_begin_drain_session(clp); |
2055 | cred = nfs4_get_exchange_id_cred(clp); | 2040 | cred = nfs4_get_clid_cred(clp); |
2056 | status = nfs4_proc_destroy_session(clp->cl_session, cred); | 2041 | status = nfs4_proc_destroy_session(clp->cl_session, cred); |
2057 | switch (status) { | 2042 | switch (status) { |
2058 | case 0: | 2043 | case 0: |
@@ -2095,7 +2080,7 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
2095 | if (!nfs4_has_session(clp)) | 2080 | if (!nfs4_has_session(clp)) |
2096 | return 0; | 2081 | return 0; |
2097 | nfs4_begin_drain_session(clp); | 2082 | nfs4_begin_drain_session(clp); |
2098 | cred = nfs4_get_exchange_id_cred(clp); | 2083 | cred = nfs4_get_clid_cred(clp); |
2099 | ret = nfs4_proc_bind_conn_to_session(clp, cred); | 2084 | ret = nfs4_proc_bind_conn_to_session(clp, cred); |
2100 | if (cred) | 2085 | if (cred) |
2101 | put_rpccred(cred); | 2086 | put_rpccred(cred); |
@@ -2116,7 +2101,6 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
2116 | } | 2101 | } |
2117 | #else /* CONFIG_NFS_V4_1 */ | 2102 | #else /* CONFIG_NFS_V4_1 */ |
2118 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 2103 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
2119 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | ||
2120 | 2104 | ||
2121 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | 2105 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) |
2122 | { | 2106 | { |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 5dbe2d269210..e26acdd1a645 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -253,8 +253,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name, | |||
253 | 253 | ||
254 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); | 254 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); |
255 | 255 | ||
256 | if (data->auth_flavors[0] == RPC_AUTH_MAXFLAVOR) | ||
257 | data->auth_flavors[0] = RPC_AUTH_UNIX; | ||
258 | export_path = data->nfs_server.export_path; | 256 | export_path = data->nfs_server.export_path; |
259 | data->nfs_server.export_path = "/"; | 257 | data->nfs_server.export_path = "/"; |
260 | root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, | 258 | root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, |
diff --git a/fs/nfs/nfs4trace.c b/fs/nfs/nfs4trace.c new file mode 100644 index 000000000000..d774335cc8bc --- /dev/null +++ b/fs/nfs/nfs4trace.c | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
3 | */ | ||
4 | #include <linux/nfs_fs.h> | ||
5 | #include "nfs4_fs.h" | ||
6 | #include "internal.h" | ||
7 | #include "nfs4session.h" | ||
8 | #include "callback.h" | ||
9 | |||
10 | #define CREATE_TRACE_POINTS | ||
11 | #include "nfs4trace.h" | ||
12 | |||
13 | #ifdef CONFIG_NFS_V4_1 | ||
14 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs4_pnfs_read); | ||
15 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs4_pnfs_write); | ||
16 | EXPORT_TRACEPOINT_SYMBOL_GPL(nfs4_pnfs_commit_ds); | ||
17 | #endif | ||
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h new file mode 100644 index 000000000000..849cf146db30 --- /dev/null +++ b/fs/nfs/nfs4trace.h | |||
@@ -0,0 +1,1148 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
3 | */ | ||
4 | #undef TRACE_SYSTEM | ||
5 | #define TRACE_SYSTEM nfs4 | ||
6 | |||
7 | #if !defined(_TRACE_NFS4_H) || defined(TRACE_HEADER_MULTI_READ) | ||
8 | #define _TRACE_NFS4_H | ||
9 | |||
10 | #include <linux/tracepoint.h> | ||
11 | |||
12 | #define show_nfsv4_errors(error) \ | ||
13 | __print_symbolic(error, \ | ||
14 | { NFS4_OK, "OK" }, \ | ||
15 | /* Mapped by nfs4_stat_to_errno() */ \ | ||
16 | { -EPERM, "EPERM" }, \ | ||
17 | { -ENOENT, "ENOENT" }, \ | ||
18 | { -EIO, "EIO" }, \ | ||
19 | { -ENXIO, "ENXIO" }, \ | ||
20 | { -EACCES, "EACCES" }, \ | ||
21 | { -EEXIST, "EEXIST" }, \ | ||
22 | { -EXDEV, "EXDEV" }, \ | ||
23 | { -ENOTDIR, "ENOTDIR" }, \ | ||
24 | { -EISDIR, "EISDIR" }, \ | ||
25 | { -EFBIG, "EFBIG" }, \ | ||
26 | { -ENOSPC, "ENOSPC" }, \ | ||
27 | { -EROFS, "EROFS" }, \ | ||
28 | { -EMLINK, "EMLINK" }, \ | ||
29 | { -ENAMETOOLONG, "ENAMETOOLONG" }, \ | ||
30 | { -ENOTEMPTY, "ENOTEMPTY" }, \ | ||
31 | { -EDQUOT, "EDQUOT" }, \ | ||
32 | { -ESTALE, "ESTALE" }, \ | ||
33 | { -EBADHANDLE, "EBADHANDLE" }, \ | ||
34 | { -EBADCOOKIE, "EBADCOOKIE" }, \ | ||
35 | { -ENOTSUPP, "ENOTSUPP" }, \ | ||
36 | { -ETOOSMALL, "ETOOSMALL" }, \ | ||
37 | { -EREMOTEIO, "EREMOTEIO" }, \ | ||
38 | { -EBADTYPE, "EBADTYPE" }, \ | ||
39 | { -EAGAIN, "EAGAIN" }, \ | ||
40 | { -ELOOP, "ELOOP" }, \ | ||
41 | { -EOPNOTSUPP, "EOPNOTSUPP" }, \ | ||
42 | { -EDEADLK, "EDEADLK" }, \ | ||
43 | /* RPC errors */ \ | ||
44 | { -ENOMEM, "ENOMEM" }, \ | ||
45 | { -EKEYEXPIRED, "EKEYEXPIRED" }, \ | ||
46 | { -ETIMEDOUT, "ETIMEDOUT" }, \ | ||
47 | { -ERESTARTSYS, "ERESTARTSYS" }, \ | ||
48 | { -ECONNREFUSED, "ECONNREFUSED" }, \ | ||
49 | { -ECONNRESET, "ECONNRESET" }, \ | ||
50 | { -ENETUNREACH, "ENETUNREACH" }, \ | ||
51 | { -EHOSTUNREACH, "EHOSTUNREACH" }, \ | ||
52 | { -EHOSTDOWN, "EHOSTDOWN" }, \ | ||
53 | { -EPIPE, "EPIPE" }, \ | ||
54 | { -EPFNOSUPPORT, "EPFNOSUPPORT" }, \ | ||
55 | { -EPROTONOSUPPORT, "EPROTONOSUPPORT" }, \ | ||
56 | /* NFSv4 native errors */ \ | ||
57 | { -NFS4ERR_ACCESS, "ACCESS" }, \ | ||
58 | { -NFS4ERR_ATTRNOTSUPP, "ATTRNOTSUPP" }, \ | ||
59 | { -NFS4ERR_ADMIN_REVOKED, "ADMIN_REVOKED" }, \ | ||
60 | { -NFS4ERR_BACK_CHAN_BUSY, "BACK_CHAN_BUSY" }, \ | ||
61 | { -NFS4ERR_BADCHAR, "BADCHAR" }, \ | ||
62 | { -NFS4ERR_BADHANDLE, "BADHANDLE" }, \ | ||
63 | { -NFS4ERR_BADIOMODE, "BADIOMODE" }, \ | ||
64 | { -NFS4ERR_BADLAYOUT, "BADLAYOUT" }, \ | ||
65 | { -NFS4ERR_BADLABEL, "BADLABEL" }, \ | ||
66 | { -NFS4ERR_BADNAME, "BADNAME" }, \ | ||
67 | { -NFS4ERR_BADOWNER, "BADOWNER" }, \ | ||
68 | { -NFS4ERR_BADSESSION, "BADSESSION" }, \ | ||
69 | { -NFS4ERR_BADSLOT, "BADSLOT" }, \ | ||
70 | { -NFS4ERR_BADTYPE, "BADTYPE" }, \ | ||
71 | { -NFS4ERR_BADXDR, "BADXDR" }, \ | ||
72 | { -NFS4ERR_BAD_COOKIE, "BAD_COOKIE" }, \ | ||
73 | { -NFS4ERR_BAD_HIGH_SLOT, "BAD_HIGH_SLOT" }, \ | ||
74 | { -NFS4ERR_BAD_RANGE, "BAD_RANGE" }, \ | ||
75 | { -NFS4ERR_BAD_SEQID, "BAD_SEQID" }, \ | ||
76 | { -NFS4ERR_BAD_SESSION_DIGEST, "BAD_SESSION_DIGEST" }, \ | ||
77 | { -NFS4ERR_BAD_STATEID, "BAD_STATEID" }, \ | ||
78 | { -NFS4ERR_CB_PATH_DOWN, "CB_PATH_DOWN" }, \ | ||
79 | { -NFS4ERR_CLID_INUSE, "CLID_INUSE" }, \ | ||
80 | { -NFS4ERR_CLIENTID_BUSY, "CLIENTID_BUSY" }, \ | ||
81 | { -NFS4ERR_COMPLETE_ALREADY, "COMPLETE_ALREADY" }, \ | ||
82 | { -NFS4ERR_CONN_NOT_BOUND_TO_SESSION, \ | ||
83 | "CONN_NOT_BOUND_TO_SESSION" }, \ | ||
84 | { -NFS4ERR_DEADLOCK, "DEADLOCK" }, \ | ||
85 | { -NFS4ERR_DEADSESSION, "DEAD_SESSION" }, \ | ||
86 | { -NFS4ERR_DELAY, "DELAY" }, \ | ||
87 | { -NFS4ERR_DELEG_ALREADY_WANTED, \ | ||
88 | "DELEG_ALREADY_WANTED" }, \ | ||
89 | { -NFS4ERR_DELEG_REVOKED, "DELEG_REVOKED" }, \ | ||
90 | { -NFS4ERR_DENIED, "DENIED" }, \ | ||
91 | { -NFS4ERR_DIRDELEG_UNAVAIL, "DIRDELEG_UNAVAIL" }, \ | ||
92 | { -NFS4ERR_DQUOT, "DQUOT" }, \ | ||
93 | { -NFS4ERR_ENCR_ALG_UNSUPP, "ENCR_ALG_UNSUPP" }, \ | ||
94 | { -NFS4ERR_EXIST, "EXIST" }, \ | ||
95 | { -NFS4ERR_EXPIRED, "EXPIRED" }, \ | ||
96 | { -NFS4ERR_FBIG, "FBIG" }, \ | ||
97 | { -NFS4ERR_FHEXPIRED, "FHEXPIRED" }, \ | ||
98 | { -NFS4ERR_FILE_OPEN, "FILE_OPEN" }, \ | ||
99 | { -NFS4ERR_GRACE, "GRACE" }, \ | ||
100 | { -NFS4ERR_HASH_ALG_UNSUPP, "HASH_ALG_UNSUPP" }, \ | ||
101 | { -NFS4ERR_INVAL, "INVAL" }, \ | ||
102 | { -NFS4ERR_IO, "IO" }, \ | ||
103 | { -NFS4ERR_ISDIR, "ISDIR" }, \ | ||
104 | { -NFS4ERR_LAYOUTTRYLATER, "LAYOUTTRYLATER" }, \ | ||
105 | { -NFS4ERR_LAYOUTUNAVAILABLE, "LAYOUTUNAVAILABLE" }, \ | ||
106 | { -NFS4ERR_LEASE_MOVED, "LEASE_MOVED" }, \ | ||
107 | { -NFS4ERR_LOCKED, "LOCKED" }, \ | ||
108 | { -NFS4ERR_LOCKS_HELD, "LOCKS_HELD" }, \ | ||
109 | { -NFS4ERR_LOCK_RANGE, "LOCK_RANGE" }, \ | ||
110 | { -NFS4ERR_MINOR_VERS_MISMATCH, "MINOR_VERS_MISMATCH" }, \ | ||
111 | { -NFS4ERR_MLINK, "MLINK" }, \ | ||
112 | { -NFS4ERR_MOVED, "MOVED" }, \ | ||
113 | { -NFS4ERR_NAMETOOLONG, "NAMETOOLONG" }, \ | ||
114 | { -NFS4ERR_NOENT, "NOENT" }, \ | ||
115 | { -NFS4ERR_NOFILEHANDLE, "NOFILEHANDLE" }, \ | ||
116 | { -NFS4ERR_NOMATCHING_LAYOUT, "NOMATCHING_LAYOUT" }, \ | ||
117 | { -NFS4ERR_NOSPC, "NOSPC" }, \ | ||
118 | { -NFS4ERR_NOTDIR, "NOTDIR" }, \ | ||
119 | { -NFS4ERR_NOTEMPTY, "NOTEMPTY" }, \ | ||
120 | { -NFS4ERR_NOTSUPP, "NOTSUPP" }, \ | ||
121 | { -NFS4ERR_NOT_ONLY_OP, "NOT_ONLY_OP" }, \ | ||
122 | { -NFS4ERR_NOT_SAME, "NOT_SAME" }, \ | ||
123 | { -NFS4ERR_NO_GRACE, "NO_GRACE" }, \ | ||
124 | { -NFS4ERR_NXIO, "NXIO" }, \ | ||
125 | { -NFS4ERR_OLD_STATEID, "OLD_STATEID" }, \ | ||
126 | { -NFS4ERR_OPENMODE, "OPENMODE" }, \ | ||
127 | { -NFS4ERR_OP_ILLEGAL, "OP_ILLEGAL" }, \ | ||
128 | { -NFS4ERR_OP_NOT_IN_SESSION, "OP_NOT_IN_SESSION" }, \ | ||
129 | { -NFS4ERR_PERM, "PERM" }, \ | ||
130 | { -NFS4ERR_PNFS_IO_HOLE, "PNFS_IO_HOLE" }, \ | ||
131 | { -NFS4ERR_PNFS_NO_LAYOUT, "PNFS_NO_LAYOUT" }, \ | ||
132 | { -NFS4ERR_RECALLCONFLICT, "RECALLCONFLICT" }, \ | ||
133 | { -NFS4ERR_RECLAIM_BAD, "RECLAIM_BAD" }, \ | ||
134 | { -NFS4ERR_RECLAIM_CONFLICT, "RECLAIM_CONFLICT" }, \ | ||
135 | { -NFS4ERR_REJECT_DELEG, "REJECT_DELEG" }, \ | ||
136 | { -NFS4ERR_REP_TOO_BIG, "REP_TOO_BIG" }, \ | ||
137 | { -NFS4ERR_REP_TOO_BIG_TO_CACHE, \ | ||
138 | "REP_TOO_BIG_TO_CACHE" }, \ | ||
139 | { -NFS4ERR_REQ_TOO_BIG, "REQ_TOO_BIG" }, \ | ||
140 | { -NFS4ERR_RESOURCE, "RESOURCE" }, \ | ||
141 | { -NFS4ERR_RESTOREFH, "RESTOREFH" }, \ | ||
142 | { -NFS4ERR_RETRY_UNCACHED_REP, "RETRY_UNCACHED_REP" }, \ | ||
143 | { -NFS4ERR_RETURNCONFLICT, "RETURNCONFLICT" }, \ | ||
144 | { -NFS4ERR_ROFS, "ROFS" }, \ | ||
145 | { -NFS4ERR_SAME, "SAME" }, \ | ||
146 | { -NFS4ERR_SHARE_DENIED, "SHARE_DENIED" }, \ | ||
147 | { -NFS4ERR_SEQUENCE_POS, "SEQUENCE_POS" }, \ | ||
148 | { -NFS4ERR_SEQ_FALSE_RETRY, "SEQ_FALSE_RETRY" }, \ | ||
149 | { -NFS4ERR_SEQ_MISORDERED, "SEQ_MISORDERED" }, \ | ||
150 | { -NFS4ERR_SERVERFAULT, "SERVERFAULT" }, \ | ||
151 | { -NFS4ERR_STALE, "STALE" }, \ | ||
152 | { -NFS4ERR_STALE_CLIENTID, "STALE_CLIENTID" }, \ | ||
153 | { -NFS4ERR_STALE_STATEID, "STALE_STATEID" }, \ | ||
154 | { -NFS4ERR_SYMLINK, "SYMLINK" }, \ | ||
155 | { -NFS4ERR_TOOSMALL, "TOOSMALL" }, \ | ||
156 | { -NFS4ERR_TOO_MANY_OPS, "TOO_MANY_OPS" }, \ | ||
157 | { -NFS4ERR_UNKNOWN_LAYOUTTYPE, "UNKNOWN_LAYOUTTYPE" }, \ | ||
158 | { -NFS4ERR_UNSAFE_COMPOUND, "UNSAFE_COMPOUND" }, \ | ||
159 | { -NFS4ERR_WRONGSEC, "WRONGSEC" }, \ | ||
160 | { -NFS4ERR_WRONG_CRED, "WRONG_CRED" }, \ | ||
161 | { -NFS4ERR_WRONG_TYPE, "WRONG_TYPE" }, \ | ||
162 | { -NFS4ERR_XDEV, "XDEV" }) | ||
163 | |||
164 | #define show_open_flags(flags) \ | ||
165 | __print_flags(flags, "|", \ | ||
166 | { O_CREAT, "O_CREAT" }, \ | ||
167 | { O_EXCL, "O_EXCL" }, \ | ||
168 | { O_TRUNC, "O_TRUNC" }, \ | ||
169 | { O_DIRECT, "O_DIRECT" }) | ||
170 | |||
171 | #define show_fmode_flags(mode) \ | ||
172 | __print_flags(mode, "|", \ | ||
173 | { ((__force unsigned long)FMODE_READ), "READ" }, \ | ||
174 | { ((__force unsigned long)FMODE_WRITE), "WRITE" }, \ | ||
175 | { ((__force unsigned long)FMODE_EXEC), "EXEC" }) | ||
176 | |||
177 | #define show_nfs_fattr_flags(valid) \ | ||
178 | __print_flags((unsigned long)valid, "|", \ | ||
179 | { NFS_ATTR_FATTR_TYPE, "TYPE" }, \ | ||
180 | { NFS_ATTR_FATTR_MODE, "MODE" }, \ | ||
181 | { NFS_ATTR_FATTR_NLINK, "NLINK" }, \ | ||
182 | { NFS_ATTR_FATTR_OWNER, "OWNER" }, \ | ||
183 | { NFS_ATTR_FATTR_GROUP, "GROUP" }, \ | ||
184 | { NFS_ATTR_FATTR_RDEV, "RDEV" }, \ | ||
185 | { NFS_ATTR_FATTR_SIZE, "SIZE" }, \ | ||
186 | { NFS_ATTR_FATTR_FSID, "FSID" }, \ | ||
187 | { NFS_ATTR_FATTR_FILEID, "FILEID" }, \ | ||
188 | { NFS_ATTR_FATTR_ATIME, "ATIME" }, \ | ||
189 | { NFS_ATTR_FATTR_MTIME, "MTIME" }, \ | ||
190 | { NFS_ATTR_FATTR_CTIME, "CTIME" }, \ | ||
191 | { NFS_ATTR_FATTR_CHANGE, "CHANGE" }, \ | ||
192 | { NFS_ATTR_FATTR_OWNER_NAME, "OWNER_NAME" }, \ | ||
193 | { NFS_ATTR_FATTR_GROUP_NAME, "GROUP_NAME" }) | ||
194 | |||
195 | DECLARE_EVENT_CLASS(nfs4_clientid_event, | ||
196 | TP_PROTO( | ||
197 | const struct nfs_client *clp, | ||
198 | int error | ||
199 | ), | ||
200 | |||
201 | TP_ARGS(clp, error), | ||
202 | |||
203 | TP_STRUCT__entry( | ||
204 | __string(dstaddr, | ||
205 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
206 | RPC_DISPLAY_ADDR)) | ||
207 | __field(int, error) | ||
208 | ), | ||
209 | |||
210 | TP_fast_assign( | ||
211 | __entry->error = error; | ||
212 | __assign_str(dstaddr, | ||
213 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
214 | RPC_DISPLAY_ADDR)); | ||
215 | ), | ||
216 | |||
217 | TP_printk( | ||
218 | "error=%d (%s) dstaddr=%s", | ||
219 | __entry->error, | ||
220 | show_nfsv4_errors(__entry->error), | ||
221 | __get_str(dstaddr) | ||
222 | ) | ||
223 | ); | ||
224 | #define DEFINE_NFS4_CLIENTID_EVENT(name) \ | ||
225 | DEFINE_EVENT(nfs4_clientid_event, name, \ | ||
226 | TP_PROTO( \ | ||
227 | const struct nfs_client *clp, \ | ||
228 | int error \ | ||
229 | ), \ | ||
230 | TP_ARGS(clp, error)) | ||
231 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_setclientid); | ||
232 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_setclientid_confirm); | ||
233 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_renew); | ||
234 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_renew_async); | ||
235 | #ifdef CONFIG_NFS_V4_1 | ||
236 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_exchange_id); | ||
237 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_create_session); | ||
238 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_destroy_session); | ||
239 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_destroy_clientid); | ||
240 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_bind_conn_to_session); | ||
241 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_sequence); | ||
242 | DEFINE_NFS4_CLIENTID_EVENT(nfs4_reclaim_complete); | ||
243 | |||
244 | TRACE_EVENT(nfs4_setup_sequence, | ||
245 | TP_PROTO( | ||
246 | const struct nfs4_session *session, | ||
247 | const struct nfs4_sequence_args *args | ||
248 | ), | ||
249 | TP_ARGS(session, args), | ||
250 | |||
251 | TP_STRUCT__entry( | ||
252 | __field(unsigned int, session) | ||
253 | __field(unsigned int, slot_nr) | ||
254 | __field(unsigned int, seq_nr) | ||
255 | __field(unsigned int, highest_used_slotid) | ||
256 | ), | ||
257 | |||
258 | TP_fast_assign( | ||
259 | const struct nfs4_slot *sa_slot = args->sa_slot; | ||
260 | __entry->session = nfs_session_id_hash(&session->sess_id); | ||
261 | __entry->slot_nr = sa_slot->slot_nr; | ||
262 | __entry->seq_nr = sa_slot->seq_nr; | ||
263 | __entry->highest_used_slotid = | ||
264 | sa_slot->table->highest_used_slotid; | ||
265 | ), | ||
266 | TP_printk( | ||
267 | "session=0x%08x slot_nr=%u seq_nr=%u " | ||
268 | "highest_used_slotid=%u", | ||
269 | __entry->session, | ||
270 | __entry->slot_nr, | ||
271 | __entry->seq_nr, | ||
272 | __entry->highest_used_slotid | ||
273 | ) | ||
274 | ); | ||
275 | |||
276 | #define show_nfs4_sequence_status_flags(status) \ | ||
277 | __print_flags((unsigned long)status, "|", \ | ||
278 | { SEQ4_STATUS_CB_PATH_DOWN, "CB_PATH_DOWN" }, \ | ||
279 | { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING, \ | ||
280 | "CB_GSS_CONTEXTS_EXPIRING" }, \ | ||
281 | { SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED, \ | ||
282 | "CB_GSS_CONTEXTS_EXPIRED" }, \ | ||
283 | { SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED, \ | ||
284 | "EXPIRED_ALL_STATE_REVOKED" }, \ | ||
285 | { SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED, \ | ||
286 | "EXPIRED_SOME_STATE_REVOKED" }, \ | ||
287 | { SEQ4_STATUS_ADMIN_STATE_REVOKED, \ | ||
288 | "ADMIN_STATE_REVOKED" }, \ | ||
289 | { SEQ4_STATUS_RECALLABLE_STATE_REVOKED, \ | ||
290 | "RECALLABLE_STATE_REVOKED" }, \ | ||
291 | { SEQ4_STATUS_LEASE_MOVED, "LEASE_MOVED" }, \ | ||
292 | { SEQ4_STATUS_RESTART_RECLAIM_NEEDED, \ | ||
293 | "RESTART_RECLAIM_NEEDED" }, \ | ||
294 | { SEQ4_STATUS_CB_PATH_DOWN_SESSION, \ | ||
295 | "CB_PATH_DOWN_SESSION" }, \ | ||
296 | { SEQ4_STATUS_BACKCHANNEL_FAULT, \ | ||
297 | "BACKCHANNEL_FAULT" }) | ||
298 | |||
299 | TRACE_EVENT(nfs4_sequence_done, | ||
300 | TP_PROTO( | ||
301 | const struct nfs4_session *session, | ||
302 | const struct nfs4_sequence_res *res | ||
303 | ), | ||
304 | TP_ARGS(session, res), | ||
305 | |||
306 | TP_STRUCT__entry( | ||
307 | __field(unsigned int, session) | ||
308 | __field(unsigned int, slot_nr) | ||
309 | __field(unsigned int, seq_nr) | ||
310 | __field(unsigned int, highest_slotid) | ||
311 | __field(unsigned int, target_highest_slotid) | ||
312 | __field(unsigned int, status_flags) | ||
313 | __field(int, error) | ||
314 | ), | ||
315 | |||
316 | TP_fast_assign( | ||
317 | const struct nfs4_slot *sr_slot = res->sr_slot; | ||
318 | __entry->session = nfs_session_id_hash(&session->sess_id); | ||
319 | __entry->slot_nr = sr_slot->slot_nr; | ||
320 | __entry->seq_nr = sr_slot->seq_nr; | ||
321 | __entry->highest_slotid = res->sr_highest_slotid; | ||
322 | __entry->target_highest_slotid = | ||
323 | res->sr_target_highest_slotid; | ||
324 | __entry->error = res->sr_status; | ||
325 | ), | ||
326 | TP_printk( | ||
327 | "error=%d (%s) session=0x%08x slot_nr=%u seq_nr=%u " | ||
328 | "highest_slotid=%u target_highest_slotid=%u " | ||
329 | "status_flags=%u (%s)", | ||
330 | __entry->error, | ||
331 | show_nfsv4_errors(__entry->error), | ||
332 | __entry->session, | ||
333 | __entry->slot_nr, | ||
334 | __entry->seq_nr, | ||
335 | __entry->highest_slotid, | ||
336 | __entry->target_highest_slotid, | ||
337 | __entry->status_flags, | ||
338 | show_nfs4_sequence_status_flags(__entry->status_flags) | ||
339 | ) | ||
340 | ); | ||
341 | |||
342 | struct cb_sequenceargs; | ||
343 | struct cb_sequenceres; | ||
344 | |||
345 | TRACE_EVENT(nfs4_cb_sequence, | ||
346 | TP_PROTO( | ||
347 | const struct cb_sequenceargs *args, | ||
348 | const struct cb_sequenceres *res, | ||
349 | __be32 status | ||
350 | ), | ||
351 | TP_ARGS(args, res, status), | ||
352 | |||
353 | TP_STRUCT__entry( | ||
354 | __field(unsigned int, session) | ||
355 | __field(unsigned int, slot_nr) | ||
356 | __field(unsigned int, seq_nr) | ||
357 | __field(unsigned int, highest_slotid) | ||
358 | __field(unsigned int, cachethis) | ||
359 | __field(int, error) | ||
360 | ), | ||
361 | |||
362 | TP_fast_assign( | ||
363 | __entry->session = nfs_session_id_hash(&args->csa_sessionid); | ||
364 | __entry->slot_nr = args->csa_slotid; | ||
365 | __entry->seq_nr = args->csa_sequenceid; | ||
366 | __entry->highest_slotid = args->csa_highestslotid; | ||
367 | __entry->cachethis = args->csa_cachethis; | ||
368 | __entry->error = -be32_to_cpu(status); | ||
369 | ), | ||
370 | |||
371 | TP_printk( | ||
372 | "error=%d (%s) session=0x%08x slot_nr=%u seq_nr=%u " | ||
373 | "highest_slotid=%u", | ||
374 | __entry->error, | ||
375 | show_nfsv4_errors(__entry->error), | ||
376 | __entry->session, | ||
377 | __entry->slot_nr, | ||
378 | __entry->seq_nr, | ||
379 | __entry->highest_slotid | ||
380 | ) | ||
381 | ); | ||
382 | #endif /* CONFIG_NFS_V4_1 */ | ||
383 | |||
384 | DECLARE_EVENT_CLASS(nfs4_open_event, | ||
385 | TP_PROTO( | ||
386 | const struct nfs_open_context *ctx, | ||
387 | int flags, | ||
388 | int error | ||
389 | ), | ||
390 | |||
391 | TP_ARGS(ctx, flags, error), | ||
392 | |||
393 | TP_STRUCT__entry( | ||
394 | __field(int, error) | ||
395 | __field(unsigned int, flags) | ||
396 | __field(unsigned int, fmode) | ||
397 | __field(dev_t, dev) | ||
398 | __field(u32, fhandle) | ||
399 | __field(u64, fileid) | ||
400 | __field(u64, dir) | ||
401 | __string(name, ctx->dentry->d_name.name) | ||
402 | ), | ||
403 | |||
404 | TP_fast_assign( | ||
405 | const struct nfs4_state *state = ctx->state; | ||
406 | const struct inode *inode = NULL; | ||
407 | |||
408 | __entry->error = error; | ||
409 | __entry->flags = flags; | ||
410 | __entry->fmode = (__force unsigned int)ctx->mode; | ||
411 | __entry->dev = ctx->dentry->d_sb->s_dev; | ||
412 | if (!IS_ERR(state)) | ||
413 | inode = state->inode; | ||
414 | if (inode != NULL) { | ||
415 | __entry->fileid = NFS_FILEID(inode); | ||
416 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
417 | } else { | ||
418 | __entry->fileid = 0; | ||
419 | __entry->fhandle = 0; | ||
420 | } | ||
421 | __entry->dir = NFS_FILEID(ctx->dentry->d_parent->d_inode); | ||
422 | __assign_str(name, ctx->dentry->d_name.name); | ||
423 | ), | ||
424 | |||
425 | TP_printk( | ||
426 | "error=%d (%s) flags=%d (%s) fmode=%s " | ||
427 | "fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
428 | "name=%02x:%02x:%llu/%s", | ||
429 | __entry->error, | ||
430 | show_nfsv4_errors(__entry->error), | ||
431 | __entry->flags, | ||
432 | show_open_flags(__entry->flags), | ||
433 | show_fmode_flags(__entry->fmode), | ||
434 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
435 | (unsigned long long)__entry->fileid, | ||
436 | __entry->fhandle, | ||
437 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
438 | (unsigned long long)__entry->dir, | ||
439 | __get_str(name) | ||
440 | ) | ||
441 | ); | ||
442 | |||
443 | #define DEFINE_NFS4_OPEN_EVENT(name) \ | ||
444 | DEFINE_EVENT(nfs4_open_event, name, \ | ||
445 | TP_PROTO( \ | ||
446 | const struct nfs_open_context *ctx, \ | ||
447 | int flags, \ | ||
448 | int error \ | ||
449 | ), \ | ||
450 | TP_ARGS(ctx, flags, error)) | ||
451 | DEFINE_NFS4_OPEN_EVENT(nfs4_open_reclaim); | ||
452 | DEFINE_NFS4_OPEN_EVENT(nfs4_open_expired); | ||
453 | DEFINE_NFS4_OPEN_EVENT(nfs4_open_file); | ||
454 | |||
455 | TRACE_EVENT(nfs4_close, | ||
456 | TP_PROTO( | ||
457 | const struct nfs4_state *state, | ||
458 | const struct nfs_closeargs *args, | ||
459 | const struct nfs_closeres *res, | ||
460 | int error | ||
461 | ), | ||
462 | |||
463 | TP_ARGS(state, args, res, error), | ||
464 | |||
465 | TP_STRUCT__entry( | ||
466 | __field(dev_t, dev) | ||
467 | __field(u32, fhandle) | ||
468 | __field(u64, fileid) | ||
469 | __field(unsigned int, fmode) | ||
470 | __field(int, error) | ||
471 | ), | ||
472 | |||
473 | TP_fast_assign( | ||
474 | const struct inode *inode = state->inode; | ||
475 | |||
476 | __entry->dev = inode->i_sb->s_dev; | ||
477 | __entry->fileid = NFS_FILEID(inode); | ||
478 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
479 | __entry->fmode = (__force unsigned int)state->state; | ||
480 | __entry->error = error; | ||
481 | ), | ||
482 | |||
483 | TP_printk( | ||
484 | "error=%d (%s) fmode=%s fileid=%02x:%02x:%llu " | ||
485 | "fhandle=0x%08x", | ||
486 | __entry->error, | ||
487 | show_nfsv4_errors(__entry->error), | ||
488 | __entry->fmode ? show_fmode_flags(__entry->fmode) : | ||
489 | "closed", | ||
490 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
491 | (unsigned long long)__entry->fileid, | ||
492 | __entry->fhandle | ||
493 | ) | ||
494 | ); | ||
495 | |||
496 | #define show_lock_cmd(type) \ | ||
497 | __print_symbolic((int)type, \ | ||
498 | { F_GETLK, "GETLK" }, \ | ||
499 | { F_SETLK, "SETLK" }, \ | ||
500 | { F_SETLKW, "SETLKW" }) | ||
501 | #define show_lock_type(type) \ | ||
502 | __print_symbolic((int)type, \ | ||
503 | { F_RDLCK, "RDLCK" }, \ | ||
504 | { F_WRLCK, "WRLCK" }, \ | ||
505 | { F_UNLCK, "UNLCK" }) | ||
506 | |||
507 | DECLARE_EVENT_CLASS(nfs4_lock_event, | ||
508 | TP_PROTO( | ||
509 | const struct file_lock *request, | ||
510 | const struct nfs4_state *state, | ||
511 | int cmd, | ||
512 | int error | ||
513 | ), | ||
514 | |||
515 | TP_ARGS(request, state, cmd, error), | ||
516 | |||
517 | TP_STRUCT__entry( | ||
518 | __field(int, error) | ||
519 | __field(int, cmd) | ||
520 | __field(char, type) | ||
521 | __field(loff_t, start) | ||
522 | __field(loff_t, end) | ||
523 | __field(dev_t, dev) | ||
524 | __field(u32, fhandle) | ||
525 | __field(u64, fileid) | ||
526 | ), | ||
527 | |||
528 | TP_fast_assign( | ||
529 | const struct inode *inode = state->inode; | ||
530 | |||
531 | __entry->error = error; | ||
532 | __entry->cmd = cmd; | ||
533 | __entry->type = request->fl_type; | ||
534 | __entry->start = request->fl_start; | ||
535 | __entry->end = request->fl_end; | ||
536 | __entry->dev = inode->i_sb->s_dev; | ||
537 | __entry->fileid = NFS_FILEID(inode); | ||
538 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
539 | ), | ||
540 | |||
541 | TP_printk( | ||
542 | "error=%d (%s) cmd=%s:%s range=%lld:%lld " | ||
543 | "fileid=%02x:%02x:%llu fhandle=0x%08x", | ||
544 | __entry->error, | ||
545 | show_nfsv4_errors(__entry->error), | ||
546 | show_lock_cmd(__entry->cmd), | ||
547 | show_lock_type(__entry->type), | ||
548 | (long long)__entry->start, | ||
549 | (long long)__entry->end, | ||
550 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
551 | (unsigned long long)__entry->fileid, | ||
552 | __entry->fhandle | ||
553 | ) | ||
554 | ); | ||
555 | |||
556 | #define DEFINE_NFS4_LOCK_EVENT(name) \ | ||
557 | DEFINE_EVENT(nfs4_lock_event, name, \ | ||
558 | TP_PROTO( \ | ||
559 | const struct file_lock *request, \ | ||
560 | const struct nfs4_state *state, \ | ||
561 | int cmd, \ | ||
562 | int error \ | ||
563 | ), \ | ||
564 | TP_ARGS(request, state, cmd, error)) | ||
565 | DEFINE_NFS4_LOCK_EVENT(nfs4_get_lock); | ||
566 | DEFINE_NFS4_LOCK_EVENT(nfs4_set_lock); | ||
567 | DEFINE_NFS4_LOCK_EVENT(nfs4_lock_reclaim); | ||
568 | DEFINE_NFS4_LOCK_EVENT(nfs4_lock_expired); | ||
569 | DEFINE_NFS4_LOCK_EVENT(nfs4_unlock); | ||
570 | |||
571 | DECLARE_EVENT_CLASS(nfs4_set_delegation_event, | ||
572 | TP_PROTO( | ||
573 | const struct inode *inode, | ||
574 | fmode_t fmode | ||
575 | ), | ||
576 | |||
577 | TP_ARGS(inode, fmode), | ||
578 | |||
579 | TP_STRUCT__entry( | ||
580 | __field(dev_t, dev) | ||
581 | __field(u32, fhandle) | ||
582 | __field(u64, fileid) | ||
583 | __field(unsigned int, fmode) | ||
584 | ), | ||
585 | |||
586 | TP_fast_assign( | ||
587 | __entry->dev = inode->i_sb->s_dev; | ||
588 | __entry->fileid = NFS_FILEID(inode); | ||
589 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
590 | __entry->fmode = (__force unsigned int)fmode; | ||
591 | ), | ||
592 | |||
593 | TP_printk( | ||
594 | "fmode=%s fileid=%02x:%02x:%llu fhandle=0x%08x", | ||
595 | show_fmode_flags(__entry->fmode), | ||
596 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
597 | (unsigned long long)__entry->fileid, | ||
598 | __entry->fhandle | ||
599 | ) | ||
600 | ); | ||
601 | #define DEFINE_NFS4_SET_DELEGATION_EVENT(name) \ | ||
602 | DEFINE_EVENT(nfs4_set_delegation_event, name, \ | ||
603 | TP_PROTO( \ | ||
604 | const struct inode *inode, \ | ||
605 | fmode_t fmode \ | ||
606 | ), \ | ||
607 | TP_ARGS(inode, fmode)) | ||
608 | DEFINE_NFS4_SET_DELEGATION_EVENT(nfs4_set_delegation); | ||
609 | DEFINE_NFS4_SET_DELEGATION_EVENT(nfs4_reclaim_delegation); | ||
610 | |||
611 | TRACE_EVENT(nfs4_delegreturn_exit, | ||
612 | TP_PROTO( | ||
613 | const struct nfs4_delegreturnargs *args, | ||
614 | const struct nfs4_delegreturnres *res, | ||
615 | int error | ||
616 | ), | ||
617 | |||
618 | TP_ARGS(args, res, error), | ||
619 | |||
620 | TP_STRUCT__entry( | ||
621 | __field(dev_t, dev) | ||
622 | __field(u32, fhandle) | ||
623 | __field(int, error) | ||
624 | ), | ||
625 | |||
626 | TP_fast_assign( | ||
627 | __entry->dev = res->server->s_dev; | ||
628 | __entry->fhandle = nfs_fhandle_hash(args->fhandle); | ||
629 | __entry->error = error; | ||
630 | ), | ||
631 | |||
632 | TP_printk( | ||
633 | "error=%d (%s) dev=%02x:%02x fhandle=0x%08x", | ||
634 | __entry->error, | ||
635 | show_nfsv4_errors(__entry->error), | ||
636 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
637 | __entry->fhandle | ||
638 | ) | ||
639 | ); | ||
640 | |||
641 | #ifdef CONFIG_NFS_V4_1 | ||
642 | DECLARE_EVENT_CLASS(nfs4_test_stateid_event, | ||
643 | TP_PROTO( | ||
644 | const struct nfs4_state *state, | ||
645 | const struct nfs4_lock_state *lsp, | ||
646 | int error | ||
647 | ), | ||
648 | |||
649 | TP_ARGS(state, lsp, error), | ||
650 | |||
651 | TP_STRUCT__entry( | ||
652 | __field(int, error) | ||
653 | __field(dev_t, dev) | ||
654 | __field(u32, fhandle) | ||
655 | __field(u64, fileid) | ||
656 | ), | ||
657 | |||
658 | TP_fast_assign( | ||
659 | const struct inode *inode = state->inode; | ||
660 | |||
661 | __entry->error = error; | ||
662 | __entry->dev = inode->i_sb->s_dev; | ||
663 | __entry->fileid = NFS_FILEID(inode); | ||
664 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
665 | ), | ||
666 | |||
667 | TP_printk( | ||
668 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x", | ||
669 | __entry->error, | ||
670 | show_nfsv4_errors(__entry->error), | ||
671 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
672 | (unsigned long long)__entry->fileid, | ||
673 | __entry->fhandle | ||
674 | ) | ||
675 | ); | ||
676 | |||
677 | #define DEFINE_NFS4_TEST_STATEID_EVENT(name) \ | ||
678 | DEFINE_EVENT(nfs4_test_stateid_event, name, \ | ||
679 | TP_PROTO( \ | ||
680 | const struct nfs4_state *state, \ | ||
681 | const struct nfs4_lock_state *lsp, \ | ||
682 | int error \ | ||
683 | ), \ | ||
684 | TP_ARGS(state, lsp, error)) | ||
685 | DEFINE_NFS4_TEST_STATEID_EVENT(nfs4_test_delegation_stateid); | ||
686 | DEFINE_NFS4_TEST_STATEID_EVENT(nfs4_test_open_stateid); | ||
687 | DEFINE_NFS4_TEST_STATEID_EVENT(nfs4_test_lock_stateid); | ||
688 | #endif /* CONFIG_NFS_V4_1 */ | ||
689 | |||
690 | DECLARE_EVENT_CLASS(nfs4_lookup_event, | ||
691 | TP_PROTO( | ||
692 | const struct inode *dir, | ||
693 | const struct qstr *name, | ||
694 | int error | ||
695 | ), | ||
696 | |||
697 | TP_ARGS(dir, name, error), | ||
698 | |||
699 | TP_STRUCT__entry( | ||
700 | __field(dev_t, dev) | ||
701 | __field(int, error) | ||
702 | __field(u64, dir) | ||
703 | __string(name, name->name) | ||
704 | ), | ||
705 | |||
706 | TP_fast_assign( | ||
707 | __entry->dev = dir->i_sb->s_dev; | ||
708 | __entry->dir = NFS_FILEID(dir); | ||
709 | __entry->error = error; | ||
710 | __assign_str(name, name->name); | ||
711 | ), | ||
712 | |||
713 | TP_printk( | ||
714 | "error=%d (%s) name=%02x:%02x:%llu/%s", | ||
715 | __entry->error, | ||
716 | show_nfsv4_errors(__entry->error), | ||
717 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
718 | (unsigned long long)__entry->dir, | ||
719 | __get_str(name) | ||
720 | ) | ||
721 | ); | ||
722 | |||
723 | #define DEFINE_NFS4_LOOKUP_EVENT(name) \ | ||
724 | DEFINE_EVENT(nfs4_lookup_event, name, \ | ||
725 | TP_PROTO( \ | ||
726 | const struct inode *dir, \ | ||
727 | const struct qstr *name, \ | ||
728 | int error \ | ||
729 | ), \ | ||
730 | TP_ARGS(dir, name, error)) | ||
731 | |||
732 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_lookup); | ||
733 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_symlink); | ||
734 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_mkdir); | ||
735 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_mknod); | ||
736 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_remove); | ||
737 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); | ||
738 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); | ||
739 | |||
740 | TRACE_EVENT(nfs4_rename, | ||
741 | TP_PROTO( | ||
742 | const struct inode *olddir, | ||
743 | const struct qstr *oldname, | ||
744 | const struct inode *newdir, | ||
745 | const struct qstr *newname, | ||
746 | int error | ||
747 | ), | ||
748 | |||
749 | TP_ARGS(olddir, oldname, newdir, newname, error), | ||
750 | |||
751 | TP_STRUCT__entry( | ||
752 | __field(dev_t, dev) | ||
753 | __field(int, error) | ||
754 | __field(u64, olddir) | ||
755 | __string(oldname, oldname->name) | ||
756 | __field(u64, newdir) | ||
757 | __string(newname, newname->name) | ||
758 | ), | ||
759 | |||
760 | TP_fast_assign( | ||
761 | __entry->dev = olddir->i_sb->s_dev; | ||
762 | __entry->olddir = NFS_FILEID(olddir); | ||
763 | __entry->newdir = NFS_FILEID(newdir); | ||
764 | __entry->error = error; | ||
765 | __assign_str(oldname, oldname->name); | ||
766 | __assign_str(newname, newname->name); | ||
767 | ), | ||
768 | |||
769 | TP_printk( | ||
770 | "error=%d (%s) oldname=%02x:%02x:%llu/%s " | ||
771 | "newname=%02x:%02x:%llu/%s", | ||
772 | __entry->error, | ||
773 | show_nfsv4_errors(__entry->error), | ||
774 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
775 | (unsigned long long)__entry->olddir, | ||
776 | __get_str(oldname), | ||
777 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
778 | (unsigned long long)__entry->newdir, | ||
779 | __get_str(newname) | ||
780 | ) | ||
781 | ); | ||
782 | |||
783 | DECLARE_EVENT_CLASS(nfs4_inode_event, | ||
784 | TP_PROTO( | ||
785 | const struct inode *inode, | ||
786 | int error | ||
787 | ), | ||
788 | |||
789 | TP_ARGS(inode, error), | ||
790 | |||
791 | TP_STRUCT__entry( | ||
792 | __field(dev_t, dev) | ||
793 | __field(u32, fhandle) | ||
794 | __field(u64, fileid) | ||
795 | __field(int, error) | ||
796 | ), | ||
797 | |||
798 | TP_fast_assign( | ||
799 | __entry->dev = inode->i_sb->s_dev; | ||
800 | __entry->fileid = NFS_FILEID(inode); | ||
801 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
802 | __entry->error = error; | ||
803 | ), | ||
804 | |||
805 | TP_printk( | ||
806 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x", | ||
807 | __entry->error, | ||
808 | show_nfsv4_errors(__entry->error), | ||
809 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
810 | (unsigned long long)__entry->fileid, | ||
811 | __entry->fhandle | ||
812 | ) | ||
813 | ); | ||
814 | |||
815 | #define DEFINE_NFS4_INODE_EVENT(name) \ | ||
816 | DEFINE_EVENT(nfs4_inode_event, name, \ | ||
817 | TP_PROTO( \ | ||
818 | const struct inode *inode, \ | ||
819 | int error \ | ||
820 | ), \ | ||
821 | TP_ARGS(inode, error)) | ||
822 | |||
823 | DEFINE_NFS4_INODE_EVENT(nfs4_setattr); | ||
824 | DEFINE_NFS4_INODE_EVENT(nfs4_access); | ||
825 | DEFINE_NFS4_INODE_EVENT(nfs4_readlink); | ||
826 | DEFINE_NFS4_INODE_EVENT(nfs4_readdir); | ||
827 | DEFINE_NFS4_INODE_EVENT(nfs4_get_acl); | ||
828 | DEFINE_NFS4_INODE_EVENT(nfs4_set_acl); | ||
829 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
830 | DEFINE_NFS4_INODE_EVENT(nfs4_get_security_label); | ||
831 | DEFINE_NFS4_INODE_EVENT(nfs4_set_security_label); | ||
832 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | ||
833 | DEFINE_NFS4_INODE_EVENT(nfs4_recall_delegation); | ||
834 | DEFINE_NFS4_INODE_EVENT(nfs4_delegreturn); | ||
835 | |||
836 | DECLARE_EVENT_CLASS(nfs4_getattr_event, | ||
837 | TP_PROTO( | ||
838 | const struct nfs_server *server, | ||
839 | const struct nfs_fh *fhandle, | ||
840 | const struct nfs_fattr *fattr, | ||
841 | int error | ||
842 | ), | ||
843 | |||
844 | TP_ARGS(server, fhandle, fattr, error), | ||
845 | |||
846 | TP_STRUCT__entry( | ||
847 | __field(dev_t, dev) | ||
848 | __field(u32, fhandle) | ||
849 | __field(u64, fileid) | ||
850 | __field(unsigned int, valid) | ||
851 | __field(int, error) | ||
852 | ), | ||
853 | |||
854 | TP_fast_assign( | ||
855 | __entry->dev = server->s_dev; | ||
856 | __entry->valid = fattr->valid; | ||
857 | __entry->fhandle = nfs_fhandle_hash(fhandle); | ||
858 | __entry->fileid = (fattr->valid & NFS_ATTR_FATTR_FILEID) ? fattr->fileid : 0; | ||
859 | __entry->error = error; | ||
860 | ), | ||
861 | |||
862 | TP_printk( | ||
863 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
864 | "valid=%s", | ||
865 | __entry->error, | ||
866 | show_nfsv4_errors(__entry->error), | ||
867 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
868 | (unsigned long long)__entry->fileid, | ||
869 | __entry->fhandle, | ||
870 | show_nfs_fattr_flags(__entry->valid) | ||
871 | ) | ||
872 | ); | ||
873 | |||
874 | #define DEFINE_NFS4_GETATTR_EVENT(name) \ | ||
875 | DEFINE_EVENT(nfs4_getattr_event, name, \ | ||
876 | TP_PROTO( \ | ||
877 | const struct nfs_server *server, \ | ||
878 | const struct nfs_fh *fhandle, \ | ||
879 | const struct nfs_fattr *fattr, \ | ||
880 | int error \ | ||
881 | ), \ | ||
882 | TP_ARGS(server, fhandle, fattr, error)) | ||
883 | DEFINE_NFS4_GETATTR_EVENT(nfs4_getattr); | ||
884 | DEFINE_NFS4_GETATTR_EVENT(nfs4_lookup_root); | ||
885 | DEFINE_NFS4_GETATTR_EVENT(nfs4_fsinfo); | ||
886 | |||
887 | DECLARE_EVENT_CLASS(nfs4_idmap_event, | ||
888 | TP_PROTO( | ||
889 | const char *name, | ||
890 | int len, | ||
891 | u32 id, | ||
892 | int error | ||
893 | ), | ||
894 | |||
895 | TP_ARGS(name, len, id, error), | ||
896 | |||
897 | TP_STRUCT__entry( | ||
898 | __field(int, error) | ||
899 | __field(u32, id) | ||
900 | __dynamic_array(char, name, len > 0 ? len + 1 : 1) | ||
901 | ), | ||
902 | |||
903 | TP_fast_assign( | ||
904 | if (len < 0) | ||
905 | len = 0; | ||
906 | __entry->error = error < 0 ? error : 0; | ||
907 | __entry->id = id; | ||
908 | memcpy(__get_dynamic_array(name), name, len); | ||
909 | ((char *)__get_dynamic_array(name))[len] = 0; | ||
910 | ), | ||
911 | |||
912 | TP_printk( | ||
913 | "error=%d id=%u name=%s", | ||
914 | __entry->error, | ||
915 | __entry->id, | ||
916 | __get_str(name) | ||
917 | ) | ||
918 | ); | ||
919 | #define DEFINE_NFS4_IDMAP_EVENT(name) \ | ||
920 | DEFINE_EVENT(nfs4_idmap_event, name, \ | ||
921 | TP_PROTO( \ | ||
922 | const char *name, \ | ||
923 | int len, \ | ||
924 | u32 id, \ | ||
925 | int error \ | ||
926 | ), \ | ||
927 | TP_ARGS(name, len, id, error)) | ||
928 | DEFINE_NFS4_IDMAP_EVENT(nfs4_map_name_to_uid); | ||
929 | DEFINE_NFS4_IDMAP_EVENT(nfs4_map_group_to_gid); | ||
930 | DEFINE_NFS4_IDMAP_EVENT(nfs4_map_uid_to_name); | ||
931 | DEFINE_NFS4_IDMAP_EVENT(nfs4_map_gid_to_group); | ||
932 | |||
933 | DECLARE_EVENT_CLASS(nfs4_read_event, | ||
934 | TP_PROTO( | ||
935 | const struct nfs_read_data *data, | ||
936 | int error | ||
937 | ), | ||
938 | |||
939 | TP_ARGS(data, error), | ||
940 | |||
941 | TP_STRUCT__entry( | ||
942 | __field(dev_t, dev) | ||
943 | __field(u32, fhandle) | ||
944 | __field(u64, fileid) | ||
945 | __field(loff_t, offset) | ||
946 | __field(size_t, count) | ||
947 | __field(int, error) | ||
948 | ), | ||
949 | |||
950 | TP_fast_assign( | ||
951 | const struct inode *inode = data->header->inode; | ||
952 | __entry->dev = inode->i_sb->s_dev; | ||
953 | __entry->fileid = NFS_FILEID(inode); | ||
954 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
955 | __entry->offset = data->args.offset; | ||
956 | __entry->count = data->args.count; | ||
957 | __entry->error = error; | ||
958 | ), | ||
959 | |||
960 | TP_printk( | ||
961 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
962 | "offset=%lld count=%zu", | ||
963 | __entry->error, | ||
964 | show_nfsv4_errors(__entry->error), | ||
965 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
966 | (unsigned long long)__entry->fileid, | ||
967 | __entry->fhandle, | ||
968 | (long long)__entry->offset, | ||
969 | __entry->count | ||
970 | ) | ||
971 | ); | ||
972 | #define DEFINE_NFS4_READ_EVENT(name) \ | ||
973 | DEFINE_EVENT(nfs4_read_event, name, \ | ||
974 | TP_PROTO( \ | ||
975 | const struct nfs_read_data *data, \ | ||
976 | int error \ | ||
977 | ), \ | ||
978 | TP_ARGS(data, error)) | ||
979 | DEFINE_NFS4_READ_EVENT(nfs4_read); | ||
980 | #ifdef CONFIG_NFS_V4_1 | ||
981 | DEFINE_NFS4_READ_EVENT(nfs4_pnfs_read); | ||
982 | #endif /* CONFIG_NFS_V4_1 */ | ||
983 | |||
984 | DECLARE_EVENT_CLASS(nfs4_write_event, | ||
985 | TP_PROTO( | ||
986 | const struct nfs_write_data *data, | ||
987 | int error | ||
988 | ), | ||
989 | |||
990 | TP_ARGS(data, error), | ||
991 | |||
992 | TP_STRUCT__entry( | ||
993 | __field(dev_t, dev) | ||
994 | __field(u32, fhandle) | ||
995 | __field(u64, fileid) | ||
996 | __field(loff_t, offset) | ||
997 | __field(size_t, count) | ||
998 | __field(int, error) | ||
999 | ), | ||
1000 | |||
1001 | TP_fast_assign( | ||
1002 | const struct inode *inode = data->header->inode; | ||
1003 | __entry->dev = inode->i_sb->s_dev; | ||
1004 | __entry->fileid = NFS_FILEID(inode); | ||
1005 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
1006 | __entry->offset = data->args.offset; | ||
1007 | __entry->count = data->args.count; | ||
1008 | __entry->error = error; | ||
1009 | ), | ||
1010 | |||
1011 | TP_printk( | ||
1012 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
1013 | "offset=%lld count=%zu", | ||
1014 | __entry->error, | ||
1015 | show_nfsv4_errors(__entry->error), | ||
1016 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
1017 | (unsigned long long)__entry->fileid, | ||
1018 | __entry->fhandle, | ||
1019 | (long long)__entry->offset, | ||
1020 | __entry->count | ||
1021 | ) | ||
1022 | ); | ||
1023 | |||
1024 | #define DEFINE_NFS4_WRITE_EVENT(name) \ | ||
1025 | DEFINE_EVENT(nfs4_write_event, name, \ | ||
1026 | TP_PROTO( \ | ||
1027 | const struct nfs_write_data *data, \ | ||
1028 | int error \ | ||
1029 | ), \ | ||
1030 | TP_ARGS(data, error)) | ||
1031 | DEFINE_NFS4_WRITE_EVENT(nfs4_write); | ||
1032 | #ifdef CONFIG_NFS_V4_1 | ||
1033 | DEFINE_NFS4_WRITE_EVENT(nfs4_pnfs_write); | ||
1034 | #endif /* CONFIG_NFS_V4_1 */ | ||
1035 | |||
1036 | DECLARE_EVENT_CLASS(nfs4_commit_event, | ||
1037 | TP_PROTO( | ||
1038 | const struct nfs_commit_data *data, | ||
1039 | int error | ||
1040 | ), | ||
1041 | |||
1042 | TP_ARGS(data, error), | ||
1043 | |||
1044 | TP_STRUCT__entry( | ||
1045 | __field(dev_t, dev) | ||
1046 | __field(u32, fhandle) | ||
1047 | __field(u64, fileid) | ||
1048 | __field(loff_t, offset) | ||
1049 | __field(size_t, count) | ||
1050 | __field(int, error) | ||
1051 | ), | ||
1052 | |||
1053 | TP_fast_assign( | ||
1054 | const struct inode *inode = data->inode; | ||
1055 | __entry->dev = inode->i_sb->s_dev; | ||
1056 | __entry->fileid = NFS_FILEID(inode); | ||
1057 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
1058 | __entry->offset = data->args.offset; | ||
1059 | __entry->count = data->args.count; | ||
1060 | __entry->error = error; | ||
1061 | ), | ||
1062 | |||
1063 | TP_printk( | ||
1064 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
1065 | "offset=%lld count=%zu", | ||
1066 | __entry->error, | ||
1067 | show_nfsv4_errors(__entry->error), | ||
1068 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
1069 | (unsigned long long)__entry->fileid, | ||
1070 | __entry->fhandle, | ||
1071 | (long long)__entry->offset, | ||
1072 | __entry->count | ||
1073 | ) | ||
1074 | ); | ||
1075 | #define DEFINE_NFS4_COMMIT_EVENT(name) \ | ||
1076 | DEFINE_EVENT(nfs4_commit_event, name, \ | ||
1077 | TP_PROTO( \ | ||
1078 | const struct nfs_commit_data *data, \ | ||
1079 | int error \ | ||
1080 | ), \ | ||
1081 | TP_ARGS(data, error)) | ||
1082 | DEFINE_NFS4_COMMIT_EVENT(nfs4_commit); | ||
1083 | #ifdef CONFIG_NFS_V4_1 | ||
1084 | DEFINE_NFS4_COMMIT_EVENT(nfs4_pnfs_commit_ds); | ||
1085 | |||
1086 | #define show_pnfs_iomode(iomode) \ | ||
1087 | __print_symbolic(iomode, \ | ||
1088 | { IOMODE_READ, "READ" }, \ | ||
1089 | { IOMODE_RW, "RW" }, \ | ||
1090 | { IOMODE_ANY, "ANY" }) | ||
1091 | |||
1092 | TRACE_EVENT(nfs4_layoutget, | ||
1093 | TP_PROTO( | ||
1094 | const struct nfs_open_context *ctx, | ||
1095 | const struct pnfs_layout_range *args, | ||
1096 | const struct pnfs_layout_range *res, | ||
1097 | int error | ||
1098 | ), | ||
1099 | |||
1100 | TP_ARGS(ctx, args, res, error), | ||
1101 | |||
1102 | TP_STRUCT__entry( | ||
1103 | __field(dev_t, dev) | ||
1104 | __field(u32, fhandle) | ||
1105 | __field(u64, fileid) | ||
1106 | __field(u32, iomode) | ||
1107 | __field(u64, offset) | ||
1108 | __field(u64, count) | ||
1109 | __field(int, error) | ||
1110 | ), | ||
1111 | |||
1112 | TP_fast_assign( | ||
1113 | const struct inode *inode = ctx->dentry->d_inode; | ||
1114 | __entry->dev = inode->i_sb->s_dev; | ||
1115 | __entry->fileid = NFS_FILEID(inode); | ||
1116 | __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode)); | ||
1117 | __entry->iomode = args->iomode; | ||
1118 | __entry->offset = args->offset; | ||
1119 | __entry->count = args->length; | ||
1120 | __entry->error = error; | ||
1121 | ), | ||
1122 | |||
1123 | TP_printk( | ||
1124 | "error=%d (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
1125 | "iomode=%s offset=%llu count=%llu", | ||
1126 | __entry->error, | ||
1127 | show_nfsv4_errors(__entry->error), | ||
1128 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
1129 | (unsigned long long)__entry->fileid, | ||
1130 | __entry->fhandle, | ||
1131 | show_pnfs_iomode(__entry->iomode), | ||
1132 | (unsigned long long)__entry->offset, | ||
1133 | (unsigned long long)__entry->count | ||
1134 | ) | ||
1135 | ); | ||
1136 | |||
1137 | DEFINE_NFS4_INODE_EVENT(nfs4_layoutcommit); | ||
1138 | DEFINE_NFS4_INODE_EVENT(nfs4_layoutreturn); | ||
1139 | |||
1140 | #endif /* CONFIG_NFS_V4_1 */ | ||
1141 | |||
1142 | #endif /* _TRACE_NFS4_H */ | ||
1143 | |||
1144 | #undef TRACE_INCLUDE_PATH | ||
1145 | #define TRACE_INCLUDE_PATH . | ||
1146 | #define TRACE_INCLUDE_FILE nfs4trace | ||
1147 | /* This part must be outside protection */ | ||
1148 | #include <trace/define_trace.h> | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 3850b018815f..fbdad9e1719f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -294,7 +294,9 @@ static int nfs4_stat_to_errno(int); | |||
294 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ | 294 | XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ |
295 | 1 /* flags */ + \ | 295 | 1 /* flags */ + \ |
296 | 1 /* spa_how */ + \ | 296 | 1 /* spa_how */ + \ |
297 | 0 /* SP4_NONE (for now) */ + \ | 297 | /* max is SP4_MACH_CRED (for now) */ + \ |
298 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
299 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
298 | 1 /* implementation id array of size 1 */ + \ | 300 | 1 /* implementation id array of size 1 */ + \ |
299 | 1 /* nii_domain */ + \ | 301 | 1 /* nii_domain */ + \ |
300 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | 302 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
@@ -306,7 +308,9 @@ static int nfs4_stat_to_errno(int); | |||
306 | 1 /* eir_sequenceid */ + \ | 308 | 1 /* eir_sequenceid */ + \ |
307 | 1 /* eir_flags */ + \ | 309 | 1 /* eir_flags */ + \ |
308 | 1 /* spr_how */ + \ | 310 | 1 /* spr_how */ + \ |
309 | 0 /* SP4_NONE (for now) */ + \ | 311 | /* max is SP4_MACH_CRED (for now) */ + \ |
312 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
313 | 1 + NFS4_OP_MAP_NUM_WORDS + \ | ||
310 | 2 /* eir_server_owner.so_minor_id */ + \ | 314 | 2 /* eir_server_owner.so_minor_id */ + \ |
311 | /* eir_server_owner.so_major_id<> */ \ | 315 | /* eir_server_owner.so_major_id<> */ \ |
312 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 316 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
@@ -997,12 +1001,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, | |||
997 | int owner_namelen = 0; | 1001 | int owner_namelen = 0; |
998 | int owner_grouplen = 0; | 1002 | int owner_grouplen = 0; |
999 | __be32 *p; | 1003 | __be32 *p; |
1000 | __be32 *q; | 1004 | unsigned i; |
1001 | int len; | 1005 | uint32_t len = 0; |
1002 | uint32_t bmval_len = 2; | 1006 | uint32_t bmval_len; |
1003 | uint32_t bmval0 = 0; | 1007 | uint32_t bmval[3] = { 0 }; |
1004 | uint32_t bmval1 = 0; | ||
1005 | uint32_t bmval2 = 0; | ||
1006 | 1008 | ||
1007 | /* | 1009 | /* |
1008 | * We reserve enough space to write the entire attribute buffer at once. | 1010 | * We reserve enough space to write the entire attribute buffer at once. |
@@ -1011,13 +1013,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, | |||
1011 | * = 40 bytes, plus any contribution from variable-length fields | 1013 | * = 40 bytes, plus any contribution from variable-length fields |
1012 | * such as owner/group. | 1014 | * such as owner/group. |
1013 | */ | 1015 | */ |
1014 | len = 8; | 1016 | if (iap->ia_valid & ATTR_SIZE) { |
1015 | 1017 | bmval[0] |= FATTR4_WORD0_SIZE; | |
1016 | /* Sigh */ | ||
1017 | if (iap->ia_valid & ATTR_SIZE) | ||
1018 | len += 8; | 1018 | len += 8; |
1019 | if (iap->ia_valid & ATTR_MODE) | 1019 | } |
1020 | if (iap->ia_valid & ATTR_MODE) { | ||
1021 | bmval[1] |= FATTR4_WORD1_MODE; | ||
1020 | len += 4; | 1022 | len += 4; |
1023 | } | ||
1021 | if (iap->ia_valid & ATTR_UID) { | 1024 | if (iap->ia_valid & ATTR_UID) { |
1022 | owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); | 1025 | owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); |
1023 | if (owner_namelen < 0) { | 1026 | if (owner_namelen < 0) { |
@@ -1028,6 +1031,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, | |||
1028 | owner_namelen = sizeof("nobody") - 1; | 1031 | owner_namelen = sizeof("nobody") - 1; |
1029 | /* goto out; */ | 1032 | /* goto out; */ |
1030 | } | 1033 | } |
1034 | bmval[1] |= FATTR4_WORD1_OWNER; | ||
1031 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); | 1035 | len += 4 + (XDR_QUADLEN(owner_namelen) << 2); |
1032 | } | 1036 | } |
1033 | if (iap->ia_valid & ATTR_GID) { | 1037 | if (iap->ia_valid & ATTR_GID) { |
@@ -1039,92 +1043,73 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, | |||
1039 | owner_grouplen = sizeof("nobody") - 1; | 1043 | owner_grouplen = sizeof("nobody") - 1; |
1040 | /* goto out; */ | 1044 | /* goto out; */ |
1041 | } | 1045 | } |
1046 | bmval[1] |= FATTR4_WORD1_OWNER_GROUP; | ||
1042 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); | 1047 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
1043 | } | 1048 | } |
1044 | if (iap->ia_valid & ATTR_ATIME_SET) | 1049 | if (iap->ia_valid & ATTR_ATIME_SET) { |
1050 | bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; | ||
1045 | len += 16; | 1051 | len += 16; |
1046 | else if (iap->ia_valid & ATTR_ATIME) | 1052 | } else if (iap->ia_valid & ATTR_ATIME) { |
1053 | bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET; | ||
1047 | len += 4; | 1054 | len += 4; |
1048 | if (iap->ia_valid & ATTR_MTIME_SET) | 1055 | } |
1056 | if (iap->ia_valid & ATTR_MTIME_SET) { | ||
1057 | bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; | ||
1049 | len += 16; | 1058 | len += 16; |
1050 | else if (iap->ia_valid & ATTR_MTIME) | 1059 | } else if (iap->ia_valid & ATTR_MTIME) { |
1060 | bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET; | ||
1051 | len += 4; | 1061 | len += 4; |
1062 | } | ||
1052 | if (label) { | 1063 | if (label) { |
1053 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); | 1064 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); |
1054 | bmval_len = 3; | 1065 | bmval[2] |= FATTR4_WORD2_SECURITY_LABEL; |
1055 | } | 1066 | } |
1056 | 1067 | ||
1057 | len += bmval_len << 2; | 1068 | if (bmval[2] != 0) |
1058 | p = reserve_space(xdr, len); | 1069 | bmval_len = 3; |
1070 | else if (bmval[1] != 0) | ||
1071 | bmval_len = 2; | ||
1072 | else | ||
1073 | bmval_len = 1; | ||
1074 | |||
1075 | p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len); | ||
1059 | 1076 | ||
1060 | /* | ||
1061 | * We write the bitmap length now, but leave the bitmap and the attribute | ||
1062 | * buffer length to be backfilled at the end of this routine. | ||
1063 | */ | ||
1064 | *p++ = cpu_to_be32(bmval_len); | 1077 | *p++ = cpu_to_be32(bmval_len); |
1065 | q = p; | 1078 | for (i = 0; i < bmval_len; i++) |
1066 | /* Skip bitmap entries + attrlen */ | 1079 | *p++ = cpu_to_be32(bmval[i]); |
1067 | p += bmval_len + 1; | 1080 | *p++ = cpu_to_be32(len); |
1068 | 1081 | ||
1069 | if (iap->ia_valid & ATTR_SIZE) { | 1082 | if (bmval[0] & FATTR4_WORD0_SIZE) |
1070 | bmval0 |= FATTR4_WORD0_SIZE; | ||
1071 | p = xdr_encode_hyper(p, iap->ia_size); | 1083 | p = xdr_encode_hyper(p, iap->ia_size); |
1072 | } | 1084 | if (bmval[1] & FATTR4_WORD1_MODE) |
1073 | if (iap->ia_valid & ATTR_MODE) { | ||
1074 | bmval1 |= FATTR4_WORD1_MODE; | ||
1075 | *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); | 1085 | *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); |
1076 | } | 1086 | if (bmval[1] & FATTR4_WORD1_OWNER) |
1077 | if (iap->ia_valid & ATTR_UID) { | ||
1078 | bmval1 |= FATTR4_WORD1_OWNER; | ||
1079 | p = xdr_encode_opaque(p, owner_name, owner_namelen); | 1087 | p = xdr_encode_opaque(p, owner_name, owner_namelen); |
1080 | } | 1088 | if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) |
1081 | if (iap->ia_valid & ATTR_GID) { | ||
1082 | bmval1 |= FATTR4_WORD1_OWNER_GROUP; | ||
1083 | p = xdr_encode_opaque(p, owner_group, owner_grouplen); | 1089 | p = xdr_encode_opaque(p, owner_group, owner_grouplen); |
1090 | if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { | ||
1091 | if (iap->ia_valid & ATTR_ATIME_SET) { | ||
1092 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); | ||
1093 | p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); | ||
1094 | *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); | ||
1095 | } else | ||
1096 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | ||
1084 | } | 1097 | } |
1085 | if (iap->ia_valid & ATTR_ATIME_SET) { | 1098 | if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { |
1086 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; | 1099 | if (iap->ia_valid & ATTR_MTIME_SET) { |
1087 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); | 1100 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); |
1088 | p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); | 1101 | p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec); |
1089 | *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); | 1102 | *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); |
1090 | } | 1103 | } else |
1091 | else if (iap->ia_valid & ATTR_ATIME) { | 1104 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1092 | bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; | ||
1093 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | ||
1094 | } | ||
1095 | if (iap->ia_valid & ATTR_MTIME_SET) { | ||
1096 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | ||
1097 | *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); | ||
1098 | p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec); | ||
1099 | *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec); | ||
1100 | } | ||
1101 | else if (iap->ia_valid & ATTR_MTIME) { | ||
1102 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | ||
1103 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | ||
1104 | } | 1105 | } |
1105 | if (label) { | 1106 | if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { |
1106 | bmval2 |= FATTR4_WORD2_SECURITY_LABEL; | ||
1107 | *p++ = cpu_to_be32(label->lfs); | 1107 | *p++ = cpu_to_be32(label->lfs); |
1108 | *p++ = cpu_to_be32(label->pi); | 1108 | *p++ = cpu_to_be32(label->pi); |
1109 | *p++ = cpu_to_be32(label->len); | 1109 | *p++ = cpu_to_be32(label->len); |
1110 | p = xdr_encode_opaque_fixed(p, label->label, label->len); | 1110 | p = xdr_encode_opaque_fixed(p, label->label, label->len); |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | /* | ||
1114 | * Now we backfill the bitmap and the attribute buffer length. | ||
1115 | */ | ||
1116 | if (len != ((char *)p - (char *)q) + 4) { | ||
1117 | printk(KERN_ERR "NFS: Attr length error, %u != %Zu\n", | ||
1118 | len, ((char *)p - (char *)q) + 4); | ||
1119 | BUG(); | ||
1120 | } | ||
1121 | *q++ = htonl(bmval0); | ||
1122 | *q++ = htonl(bmval1); | ||
1123 | if (bmval_len == 3) | ||
1124 | *q++ = htonl(bmval2); | ||
1125 | len = (char *)p - (char *)(q + 1); | ||
1126 | *q = htonl(len); | ||
1127 | |||
1128 | /* out: */ | 1113 | /* out: */ |
1129 | } | 1114 | } |
1130 | 1115 | ||
@@ -1745,6 +1730,14 @@ static void encode_bind_conn_to_session(struct xdr_stream *xdr, | |||
1745 | *p = 0; /* use_conn_in_rdma_mode = False */ | 1730 | *p = 0; /* use_conn_in_rdma_mode = False */ |
1746 | } | 1731 | } |
1747 | 1732 | ||
1733 | static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) | ||
1734 | { | ||
1735 | unsigned int i; | ||
1736 | encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS); | ||
1737 | for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) | ||
1738 | encode_uint32(xdr, op_map->u.words[i]); | ||
1739 | } | ||
1740 | |||
1748 | static void encode_exchange_id(struct xdr_stream *xdr, | 1741 | static void encode_exchange_id(struct xdr_stream *xdr, |
1749 | struct nfs41_exchange_id_args *args, | 1742 | struct nfs41_exchange_id_args *args, |
1750 | struct compound_hdr *hdr) | 1743 | struct compound_hdr *hdr) |
@@ -1758,9 +1751,20 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1758 | 1751 | ||
1759 | encode_string(xdr, args->id_len, args->id); | 1752 | encode_string(xdr, args->id_len, args->id); |
1760 | 1753 | ||
1761 | p = reserve_space(xdr, 12); | 1754 | encode_uint32(xdr, args->flags); |
1762 | *p++ = cpu_to_be32(args->flags); | 1755 | encode_uint32(xdr, args->state_protect.how); |
1763 | *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ | 1756 | |
1757 | switch (args->state_protect.how) { | ||
1758 | case SP4_NONE: | ||
1759 | break; | ||
1760 | case SP4_MACH_CRED: | ||
1761 | encode_op_map(xdr, &args->state_protect.enforce); | ||
1762 | encode_op_map(xdr, &args->state_protect.allow); | ||
1763 | break; | ||
1764 | default: | ||
1765 | WARN_ON_ONCE(1); | ||
1766 | break; | ||
1767 | } | ||
1764 | 1768 | ||
1765 | if (send_implementation_id && | 1769 | if (send_implementation_id && |
1766 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && | 1770 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && |
@@ -1771,7 +1775,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1771 | utsname()->version, utsname()->machine); | 1775 | utsname()->version, utsname()->machine); |
1772 | 1776 | ||
1773 | if (len > 0) { | 1777 | if (len > 0) { |
1774 | *p = cpu_to_be32(1); /* implementation id array length=1 */ | 1778 | encode_uint32(xdr, 1); /* implementation id array length=1 */ |
1775 | 1779 | ||
1776 | encode_string(xdr, | 1780 | encode_string(xdr, |
1777 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, | 1781 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, |
@@ -1782,7 +1786,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1782 | p = xdr_encode_hyper(p, 0); | 1786 | p = xdr_encode_hyper(p, 0); |
1783 | *p = cpu_to_be32(0); | 1787 | *p = cpu_to_be32(0); |
1784 | } else | 1788 | } else |
1785 | *p = cpu_to_be32(0); /* implementation id array length=0 */ | 1789 | encode_uint32(xdr, 0); /* implementation id array length=0 */ |
1786 | } | 1790 | } |
1787 | 1791 | ||
1788 | static void encode_create_session(struct xdr_stream *xdr, | 1792 | static void encode_create_session(struct xdr_stream *xdr, |
@@ -1835,7 +1839,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1835 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ | 1839 | *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ |
1836 | 1840 | ||
1837 | /* authsys_parms rfc1831 */ | 1841 | /* authsys_parms rfc1831 */ |
1838 | *p++ = (__be32)nn->boot_time.tv_nsec; /* stamp */ | 1842 | *p++ = cpu_to_be32(nn->boot_time.tv_nsec); /* stamp */ |
1839 | p = xdr_encode_opaque(p, machine_name, len); | 1843 | p = xdr_encode_opaque(p, machine_name, len); |
1840 | *p++ = cpu_to_be32(0); /* UID */ | 1844 | *p++ = cpu_to_be32(0); /* UID */ |
1841 | *p++ = cpu_to_be32(0); /* GID */ | 1845 | *p++ = cpu_to_be32(0); /* GID */ |
@@ -1877,11 +1881,10 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
1877 | struct nfs4_slot *slot = args->sa_slot; | 1881 | struct nfs4_slot *slot = args->sa_slot; |
1878 | __be32 *p; | 1882 | __be32 *p; |
1879 | 1883 | ||
1880 | if (slot == NULL) | ||
1881 | return; | ||
1882 | |||
1883 | tp = slot->table; | 1884 | tp = slot->table; |
1884 | session = tp->session; | 1885 | session = tp->session; |
1886 | if (!session) | ||
1887 | return; | ||
1885 | 1888 | ||
1886 | encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); | 1889 | encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); |
1887 | 1890 | ||
@@ -2062,9 +2065,9 @@ static void encode_free_stateid(struct xdr_stream *xdr, | |||
2062 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) | 2065 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) |
2063 | { | 2066 | { |
2064 | #if defined(CONFIG_NFS_V4_1) | 2067 | #if defined(CONFIG_NFS_V4_1) |
2065 | 2068 | struct nfs4_session *session = args->sa_slot->table->session; | |
2066 | if (args->sa_slot) | 2069 | if (session) |
2067 | return args->sa_slot->table->session->clp->cl_mvops->minor_version; | 2070 | return session->clp->cl_mvops->minor_version; |
2068 | #endif /* CONFIG_NFS_V4_1 */ | 2071 | #endif /* CONFIG_NFS_V4_1 */ |
2069 | return 0; | 2072 | return 0; |
2070 | } | 2073 | } |
@@ -4649,7 +4652,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | |||
4649 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, | 4652 | static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, |
4650 | uint32_t *layouttype) | 4653 | uint32_t *layouttype) |
4651 | { | 4654 | { |
4652 | uint32_t *p; | 4655 | __be32 *p; |
4653 | int num; | 4656 | int num; |
4654 | 4657 | ||
4655 | p = xdr_inline_decode(xdr, 4); | 4658 | p = xdr_inline_decode(xdr, 4); |
@@ -5394,6 +5397,23 @@ static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_re | |||
5394 | return decode_secinfo_common(xdr, res); | 5397 | return decode_secinfo_common(xdr, res); |
5395 | } | 5398 | } |
5396 | 5399 | ||
5400 | static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) | ||
5401 | { | ||
5402 | __be32 *p; | ||
5403 | uint32_t bitmap_words; | ||
5404 | unsigned int i; | ||
5405 | |||
5406 | p = xdr_inline_decode(xdr, 4); | ||
5407 | bitmap_words = be32_to_cpup(p++); | ||
5408 | if (bitmap_words > NFS4_OP_MAP_NUM_WORDS) | ||
5409 | return -EIO; | ||
5410 | p = xdr_inline_decode(xdr, 4 * bitmap_words); | ||
5411 | for (i = 0; i < bitmap_words; i++) | ||
5412 | op_map->u.words[i] = be32_to_cpup(p++); | ||
5413 | |||
5414 | return 0; | ||
5415 | } | ||
5416 | |||
5397 | static int decode_exchange_id(struct xdr_stream *xdr, | 5417 | static int decode_exchange_id(struct xdr_stream *xdr, |
5398 | struct nfs41_exchange_id_res *res) | 5418 | struct nfs41_exchange_id_res *res) |
5399 | { | 5419 | { |
@@ -5417,10 +5437,22 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5417 | res->seqid = be32_to_cpup(p++); | 5437 | res->seqid = be32_to_cpup(p++); |
5418 | res->flags = be32_to_cpup(p++); | 5438 | res->flags = be32_to_cpup(p++); |
5419 | 5439 | ||
5420 | /* We ask for SP4_NONE */ | 5440 | res->state_protect.how = be32_to_cpup(p); |
5421 | dummy = be32_to_cpup(p); | 5441 | switch (res->state_protect.how) { |
5422 | if (dummy != SP4_NONE) | 5442 | case SP4_NONE: |
5443 | break; | ||
5444 | case SP4_MACH_CRED: | ||
5445 | status = decode_op_map(xdr, &res->state_protect.enforce); | ||
5446 | if (status) | ||
5447 | return status; | ||
5448 | status = decode_op_map(xdr, &res->state_protect.allow); | ||
5449 | if (status) | ||
5450 | return status; | ||
5451 | break; | ||
5452 | default: | ||
5453 | WARN_ON_ONCE(1); | ||
5423 | return -EIO; | 5454 | return -EIO; |
5455 | } | ||
5424 | 5456 | ||
5425 | /* server_owner4.so_minor_id */ | 5457 | /* server_owner4.so_minor_id */ |
5426 | p = xdr_inline_decode(xdr, 8); | 5458 | p = xdr_inline_decode(xdr, 8); |
@@ -5614,6 +5646,8 @@ static int decode_sequence(struct xdr_stream *xdr, | |||
5614 | 5646 | ||
5615 | if (res->sr_slot == NULL) | 5647 | if (res->sr_slot == NULL) |
5616 | return 0; | 5648 | return 0; |
5649 | if (!res->sr_slot->table->session) | ||
5650 | return 0; | ||
5617 | 5651 | ||
5618 | status = decode_op_hdr(xdr, OP_SEQUENCE); | 5652 | status = decode_op_hdr(xdr, OP_SEQUENCE); |
5619 | if (!status) | 5653 | if (!status) |
diff --git a/fs/nfs/nfstrace.c b/fs/nfs/nfstrace.c new file mode 100644 index 000000000000..4eb0aead69b6 --- /dev/null +++ b/fs/nfs/nfstrace.c | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
3 | */ | ||
4 | #include <linux/nfs_fs.h> | ||
5 | #include <linux/namei.h> | ||
6 | #include "internal.h" | ||
7 | |||
8 | #define CREATE_TRACE_POINTS | ||
9 | #include "nfstrace.h" | ||
diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h new file mode 100644 index 000000000000..89fe741e58b1 --- /dev/null +++ b/fs/nfs/nfstrace.h | |||
@@ -0,0 +1,729 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
3 | */ | ||
4 | #undef TRACE_SYSTEM | ||
5 | #define TRACE_SYSTEM nfs | ||
6 | |||
7 | #if !defined(_TRACE_NFS_H) || defined(TRACE_HEADER_MULTI_READ) | ||
8 | #define _TRACE_NFS_H | ||
9 | |||
10 | #include <linux/tracepoint.h> | ||
11 | |||
12 | #define nfs_show_file_type(ftype) \ | ||
13 | __print_symbolic(ftype, \ | ||
14 | { DT_UNKNOWN, "UNKNOWN" }, \ | ||
15 | { DT_FIFO, "FIFO" }, \ | ||
16 | { DT_CHR, "CHR" }, \ | ||
17 | { DT_DIR, "DIR" }, \ | ||
18 | { DT_BLK, "BLK" }, \ | ||
19 | { DT_REG, "REG" }, \ | ||
20 | { DT_LNK, "LNK" }, \ | ||
21 | { DT_SOCK, "SOCK" }, \ | ||
22 | { DT_WHT, "WHT" }) | ||
23 | |||
24 | #define nfs_show_cache_validity(v) \ | ||
25 | __print_flags(v, "|", \ | ||
26 | { NFS_INO_INVALID_ATTR, "INVALID_ATTR" }, \ | ||
27 | { NFS_INO_INVALID_DATA, "INVALID_DATA" }, \ | ||
28 | { NFS_INO_INVALID_ATIME, "INVALID_ATIME" }, \ | ||
29 | { NFS_INO_INVALID_ACCESS, "INVALID_ACCESS" }, \ | ||
30 | { NFS_INO_INVALID_ACL, "INVALID_ACL" }, \ | ||
31 | { NFS_INO_REVAL_PAGECACHE, "REVAL_PAGECACHE" }, \ | ||
32 | { NFS_INO_REVAL_FORCED, "REVAL_FORCED" }, \ | ||
33 | { NFS_INO_INVALID_LABEL, "INVALID_LABEL" }) | ||
34 | |||
35 | #define nfs_show_nfsi_flags(v) \ | ||
36 | __print_flags(v, "|", \ | ||
37 | { 1 << NFS_INO_ADVISE_RDPLUS, "ADVISE_RDPLUS" }, \ | ||
38 | { 1 << NFS_INO_STALE, "STALE" }, \ | ||
39 | { 1 << NFS_INO_FLUSHING, "FLUSHING" }, \ | ||
40 | { 1 << NFS_INO_FSCACHE, "FSCACHE" }, \ | ||
41 | { 1 << NFS_INO_COMMIT, "COMMIT" }, \ | ||
42 | { 1 << NFS_INO_LAYOUTCOMMIT, "NEED_LAYOUTCOMMIT" }, \ | ||
43 | { 1 << NFS_INO_LAYOUTCOMMITTING, "LAYOUTCOMMIT" }) | ||
44 | |||
45 | DECLARE_EVENT_CLASS(nfs_inode_event, | ||
46 | TP_PROTO( | ||
47 | const struct inode *inode | ||
48 | ), | ||
49 | |||
50 | TP_ARGS(inode), | ||
51 | |||
52 | TP_STRUCT__entry( | ||
53 | __field(dev_t, dev) | ||
54 | __field(u32, fhandle) | ||
55 | __field(u64, fileid) | ||
56 | __field(u64, version) | ||
57 | ), | ||
58 | |||
59 | TP_fast_assign( | ||
60 | const struct nfs_inode *nfsi = NFS_I(inode); | ||
61 | __entry->dev = inode->i_sb->s_dev; | ||
62 | __entry->fileid = nfsi->fileid; | ||
63 | __entry->fhandle = nfs_fhandle_hash(&nfsi->fh); | ||
64 | __entry->version = inode->i_version; | ||
65 | ), | ||
66 | |||
67 | TP_printk( | ||
68 | "fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu ", | ||
69 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
70 | (unsigned long long)__entry->fileid, | ||
71 | __entry->fhandle, | ||
72 | (unsigned long long)__entry->version | ||
73 | ) | ||
74 | ); | ||
75 | |||
76 | DECLARE_EVENT_CLASS(nfs_inode_event_done, | ||
77 | TP_PROTO( | ||
78 | const struct inode *inode, | ||
79 | int error | ||
80 | ), | ||
81 | |||
82 | TP_ARGS(inode, error), | ||
83 | |||
84 | TP_STRUCT__entry( | ||
85 | __field(int, error) | ||
86 | __field(dev_t, dev) | ||
87 | __field(u32, fhandle) | ||
88 | __field(unsigned char, type) | ||
89 | __field(u64, fileid) | ||
90 | __field(u64, version) | ||
91 | __field(loff_t, size) | ||
92 | __field(unsigned long, nfsi_flags) | ||
93 | __field(unsigned long, cache_validity) | ||
94 | ), | ||
95 | |||
96 | TP_fast_assign( | ||
97 | const struct nfs_inode *nfsi = NFS_I(inode); | ||
98 | __entry->error = error; | ||
99 | __entry->dev = inode->i_sb->s_dev; | ||
100 | __entry->fileid = nfsi->fileid; | ||
101 | __entry->fhandle = nfs_fhandle_hash(&nfsi->fh); | ||
102 | __entry->type = nfs_umode_to_dtype(inode->i_mode); | ||
103 | __entry->version = inode->i_version; | ||
104 | __entry->size = i_size_read(inode); | ||
105 | __entry->nfsi_flags = nfsi->flags; | ||
106 | __entry->cache_validity = nfsi->cache_validity; | ||
107 | ), | ||
108 | |||
109 | TP_printk( | ||
110 | "error=%d fileid=%02x:%02x:%llu fhandle=0x%08x " | ||
111 | "type=%u (%s) version=%llu size=%lld " | ||
112 | "cache_validity=%lu (%s) nfs_flags=%ld (%s)", | ||
113 | __entry->error, | ||
114 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
115 | (unsigned long long)__entry->fileid, | ||
116 | __entry->fhandle, | ||
117 | __entry->type, | ||
118 | nfs_show_file_type(__entry->type), | ||
119 | (unsigned long long)__entry->version, | ||
120 | (long long)__entry->size, | ||
121 | __entry->cache_validity, | ||
122 | nfs_show_cache_validity(__entry->cache_validity), | ||
123 | __entry->nfsi_flags, | ||
124 | nfs_show_nfsi_flags(__entry->nfsi_flags) | ||
125 | ) | ||
126 | ); | ||
127 | |||
128 | #define DEFINE_NFS_INODE_EVENT(name) \ | ||
129 | DEFINE_EVENT(nfs_inode_event, name, \ | ||
130 | TP_PROTO( \ | ||
131 | const struct inode *inode \ | ||
132 | ), \ | ||
133 | TP_ARGS(inode)) | ||
134 | #define DEFINE_NFS_INODE_EVENT_DONE(name) \ | ||
135 | DEFINE_EVENT(nfs_inode_event_done, name, \ | ||
136 | TP_PROTO( \ | ||
137 | const struct inode *inode, \ | ||
138 | int error \ | ||
139 | ), \ | ||
140 | TP_ARGS(inode, error)) | ||
141 | DEFINE_NFS_INODE_EVENT(nfs_refresh_inode_enter); | ||
142 | DEFINE_NFS_INODE_EVENT_DONE(nfs_refresh_inode_exit); | ||
143 | DEFINE_NFS_INODE_EVENT(nfs_revalidate_inode_enter); | ||
144 | DEFINE_NFS_INODE_EVENT_DONE(nfs_revalidate_inode_exit); | ||
145 | DEFINE_NFS_INODE_EVENT(nfs_invalidate_mapping_enter); | ||
146 | DEFINE_NFS_INODE_EVENT_DONE(nfs_invalidate_mapping_exit); | ||
147 | DEFINE_NFS_INODE_EVENT(nfs_getattr_enter); | ||
148 | DEFINE_NFS_INODE_EVENT_DONE(nfs_getattr_exit); | ||
149 | DEFINE_NFS_INODE_EVENT(nfs_setattr_enter); | ||
150 | DEFINE_NFS_INODE_EVENT_DONE(nfs_setattr_exit); | ||
151 | DEFINE_NFS_INODE_EVENT(nfs_writeback_page_enter); | ||
152 | DEFINE_NFS_INODE_EVENT_DONE(nfs_writeback_page_exit); | ||
153 | DEFINE_NFS_INODE_EVENT(nfs_writeback_inode_enter); | ||
154 | DEFINE_NFS_INODE_EVENT_DONE(nfs_writeback_inode_exit); | ||
155 | DEFINE_NFS_INODE_EVENT(nfs_fsync_enter); | ||
156 | DEFINE_NFS_INODE_EVENT_DONE(nfs_fsync_exit); | ||
157 | DEFINE_NFS_INODE_EVENT(nfs_access_enter); | ||
158 | DEFINE_NFS_INODE_EVENT_DONE(nfs_access_exit); | ||
159 | |||
160 | #define show_lookup_flags(flags) \ | ||
161 | __print_flags((unsigned long)flags, "|", \ | ||
162 | { LOOKUP_AUTOMOUNT, "AUTOMOUNT" }, \ | ||
163 | { LOOKUP_DIRECTORY, "DIRECTORY" }, \ | ||
164 | { LOOKUP_OPEN, "OPEN" }, \ | ||
165 | { LOOKUP_CREATE, "CREATE" }, \ | ||
166 | { LOOKUP_EXCL, "EXCL" }) | ||
167 | |||
168 | DECLARE_EVENT_CLASS(nfs_lookup_event, | ||
169 | TP_PROTO( | ||
170 | const struct inode *dir, | ||
171 | const struct dentry *dentry, | ||
172 | unsigned int flags | ||
173 | ), | ||
174 | |||
175 | TP_ARGS(dir, dentry, flags), | ||
176 | |||
177 | TP_STRUCT__entry( | ||
178 | __field(unsigned int, flags) | ||
179 | __field(dev_t, dev) | ||
180 | __field(u64, dir) | ||
181 | __string(name, dentry->d_name.name) | ||
182 | ), | ||
183 | |||
184 | TP_fast_assign( | ||
185 | __entry->dev = dir->i_sb->s_dev; | ||
186 | __entry->dir = NFS_FILEID(dir); | ||
187 | __entry->flags = flags; | ||
188 | __assign_str(name, dentry->d_name.name); | ||
189 | ), | ||
190 | |||
191 | TP_printk( | ||
192 | "flags=%u (%s) name=%02x:%02x:%llu/%s", | ||
193 | __entry->flags, | ||
194 | show_lookup_flags(__entry->flags), | ||
195 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
196 | (unsigned long long)__entry->dir, | ||
197 | __get_str(name) | ||
198 | ) | ||
199 | ); | ||
200 | |||
201 | #define DEFINE_NFS_LOOKUP_EVENT(name) \ | ||
202 | DEFINE_EVENT(nfs_lookup_event, name, \ | ||
203 | TP_PROTO( \ | ||
204 | const struct inode *dir, \ | ||
205 | const struct dentry *dentry, \ | ||
206 | unsigned int flags \ | ||
207 | ), \ | ||
208 | TP_ARGS(dir, dentry, flags)) | ||
209 | |||
210 | DECLARE_EVENT_CLASS(nfs_lookup_event_done, | ||
211 | TP_PROTO( | ||
212 | const struct inode *dir, | ||
213 | const struct dentry *dentry, | ||
214 | unsigned int flags, | ||
215 | int error | ||
216 | ), | ||
217 | |||
218 | TP_ARGS(dir, dentry, flags, error), | ||
219 | |||
220 | TP_STRUCT__entry( | ||
221 | __field(int, error) | ||
222 | __field(unsigned int, flags) | ||
223 | __field(dev_t, dev) | ||
224 | __field(u64, dir) | ||
225 | __string(name, dentry->d_name.name) | ||
226 | ), | ||
227 | |||
228 | TP_fast_assign( | ||
229 | __entry->dev = dir->i_sb->s_dev; | ||
230 | __entry->dir = NFS_FILEID(dir); | ||
231 | __entry->error = error; | ||
232 | __entry->flags = flags; | ||
233 | __assign_str(name, dentry->d_name.name); | ||
234 | ), | ||
235 | |||
236 | TP_printk( | ||
237 | "error=%d flags=%u (%s) name=%02x:%02x:%llu/%s", | ||
238 | __entry->error, | ||
239 | __entry->flags, | ||
240 | show_lookup_flags(__entry->flags), | ||
241 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
242 | (unsigned long long)__entry->dir, | ||
243 | __get_str(name) | ||
244 | ) | ||
245 | ); | ||
246 | |||
247 | #define DEFINE_NFS_LOOKUP_EVENT_DONE(name) \ | ||
248 | DEFINE_EVENT(nfs_lookup_event_done, name, \ | ||
249 | TP_PROTO( \ | ||
250 | const struct inode *dir, \ | ||
251 | const struct dentry *dentry, \ | ||
252 | unsigned int flags, \ | ||
253 | int error \ | ||
254 | ), \ | ||
255 | TP_ARGS(dir, dentry, flags, error)) | ||
256 | |||
257 | DEFINE_NFS_LOOKUP_EVENT(nfs_lookup_enter); | ||
258 | DEFINE_NFS_LOOKUP_EVENT_DONE(nfs_lookup_exit); | ||
259 | DEFINE_NFS_LOOKUP_EVENT(nfs_lookup_revalidate_enter); | ||
260 | DEFINE_NFS_LOOKUP_EVENT_DONE(nfs_lookup_revalidate_exit); | ||
261 | |||
262 | #define show_open_flags(flags) \ | ||
263 | __print_flags((unsigned long)flags, "|", \ | ||
264 | { O_CREAT, "O_CREAT" }, \ | ||
265 | { O_EXCL, "O_EXCL" }, \ | ||
266 | { O_TRUNC, "O_TRUNC" }, \ | ||
267 | { O_APPEND, "O_APPEND" }, \ | ||
268 | { O_DSYNC, "O_DSYNC" }, \ | ||
269 | { O_DIRECT, "O_DIRECT" }, \ | ||
270 | { O_DIRECTORY, "O_DIRECTORY" }) | ||
271 | |||
272 | #define show_fmode_flags(mode) \ | ||
273 | __print_flags(mode, "|", \ | ||
274 | { ((__force unsigned long)FMODE_READ), "READ" }, \ | ||
275 | { ((__force unsigned long)FMODE_WRITE), "WRITE" }, \ | ||
276 | { ((__force unsigned long)FMODE_EXEC), "EXEC" }) | ||
277 | |||
278 | TRACE_EVENT(nfs_atomic_open_enter, | ||
279 | TP_PROTO( | ||
280 | const struct inode *dir, | ||
281 | const struct nfs_open_context *ctx, | ||
282 | unsigned int flags | ||
283 | ), | ||
284 | |||
285 | TP_ARGS(dir, ctx, flags), | ||
286 | |||
287 | TP_STRUCT__entry( | ||
288 | __field(unsigned int, flags) | ||
289 | __field(unsigned int, fmode) | ||
290 | __field(dev_t, dev) | ||
291 | __field(u64, dir) | ||
292 | __string(name, ctx->dentry->d_name.name) | ||
293 | ), | ||
294 | |||
295 | TP_fast_assign( | ||
296 | __entry->dev = dir->i_sb->s_dev; | ||
297 | __entry->dir = NFS_FILEID(dir); | ||
298 | __entry->flags = flags; | ||
299 | __entry->fmode = (__force unsigned int)ctx->mode; | ||
300 | __assign_str(name, ctx->dentry->d_name.name); | ||
301 | ), | ||
302 | |||
303 | TP_printk( | ||
304 | "flags=%u (%s) fmode=%s name=%02x:%02x:%llu/%s", | ||
305 | __entry->flags, | ||
306 | show_open_flags(__entry->flags), | ||
307 | show_fmode_flags(__entry->fmode), | ||
308 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
309 | (unsigned long long)__entry->dir, | ||
310 | __get_str(name) | ||
311 | ) | ||
312 | ); | ||
313 | |||
314 | TRACE_EVENT(nfs_atomic_open_exit, | ||
315 | TP_PROTO( | ||
316 | const struct inode *dir, | ||
317 | const struct nfs_open_context *ctx, | ||
318 | unsigned int flags, | ||
319 | int error | ||
320 | ), | ||
321 | |||
322 | TP_ARGS(dir, ctx, flags, error), | ||
323 | |||
324 | TP_STRUCT__entry( | ||
325 | __field(int, error) | ||
326 | __field(unsigned int, flags) | ||
327 | __field(unsigned int, fmode) | ||
328 | __field(dev_t, dev) | ||
329 | __field(u64, dir) | ||
330 | __string(name, ctx->dentry->d_name.name) | ||
331 | ), | ||
332 | |||
333 | TP_fast_assign( | ||
334 | __entry->error = error; | ||
335 | __entry->dev = dir->i_sb->s_dev; | ||
336 | __entry->dir = NFS_FILEID(dir); | ||
337 | __entry->flags = flags; | ||
338 | __entry->fmode = (__force unsigned int)ctx->mode; | ||
339 | __assign_str(name, ctx->dentry->d_name.name); | ||
340 | ), | ||
341 | |||
342 | TP_printk( | ||
343 | "error=%d flags=%u (%s) fmode=%s " | ||
344 | "name=%02x:%02x:%llu/%s", | ||
345 | __entry->error, | ||
346 | __entry->flags, | ||
347 | show_open_flags(__entry->flags), | ||
348 | show_fmode_flags(__entry->fmode), | ||
349 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
350 | (unsigned long long)__entry->dir, | ||
351 | __get_str(name) | ||
352 | ) | ||
353 | ); | ||
354 | |||
355 | TRACE_EVENT(nfs_create_enter, | ||
356 | TP_PROTO( | ||
357 | const struct inode *dir, | ||
358 | const struct dentry *dentry, | ||
359 | unsigned int flags | ||
360 | ), | ||
361 | |||
362 | TP_ARGS(dir, dentry, flags), | ||
363 | |||
364 | TP_STRUCT__entry( | ||
365 | __field(unsigned int, flags) | ||
366 | __field(dev_t, dev) | ||
367 | __field(u64, dir) | ||
368 | __string(name, dentry->d_name.name) | ||
369 | ), | ||
370 | |||
371 | TP_fast_assign( | ||
372 | __entry->dev = dir->i_sb->s_dev; | ||
373 | __entry->dir = NFS_FILEID(dir); | ||
374 | __entry->flags = flags; | ||
375 | __assign_str(name, dentry->d_name.name); | ||
376 | ), | ||
377 | |||
378 | TP_printk( | ||
379 | "flags=%u (%s) name=%02x:%02x:%llu/%s", | ||
380 | __entry->flags, | ||
381 | show_open_flags(__entry->flags), | ||
382 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
383 | (unsigned long long)__entry->dir, | ||
384 | __get_str(name) | ||
385 | ) | ||
386 | ); | ||
387 | |||
388 | TRACE_EVENT(nfs_create_exit, | ||
389 | TP_PROTO( | ||
390 | const struct inode *dir, | ||
391 | const struct dentry *dentry, | ||
392 | unsigned int flags, | ||
393 | int error | ||
394 | ), | ||
395 | |||
396 | TP_ARGS(dir, dentry, flags, error), | ||
397 | |||
398 | TP_STRUCT__entry( | ||
399 | __field(int, error) | ||
400 | __field(unsigned int, flags) | ||
401 | __field(dev_t, dev) | ||
402 | __field(u64, dir) | ||
403 | __string(name, dentry->d_name.name) | ||
404 | ), | ||
405 | |||
406 | TP_fast_assign( | ||
407 | __entry->error = error; | ||
408 | __entry->dev = dir->i_sb->s_dev; | ||
409 | __entry->dir = NFS_FILEID(dir); | ||
410 | __entry->flags = flags; | ||
411 | __assign_str(name, dentry->d_name.name); | ||
412 | ), | ||
413 | |||
414 | TP_printk( | ||
415 | "error=%d flags=%u (%s) name=%02x:%02x:%llu/%s", | ||
416 | __entry->error, | ||
417 | __entry->flags, | ||
418 | show_open_flags(__entry->flags), | ||
419 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
420 | (unsigned long long)__entry->dir, | ||
421 | __get_str(name) | ||
422 | ) | ||
423 | ); | ||
424 | |||
425 | DECLARE_EVENT_CLASS(nfs_directory_event, | ||
426 | TP_PROTO( | ||
427 | const struct inode *dir, | ||
428 | const struct dentry *dentry | ||
429 | ), | ||
430 | |||
431 | TP_ARGS(dir, dentry), | ||
432 | |||
433 | TP_STRUCT__entry( | ||
434 | __field(dev_t, dev) | ||
435 | __field(u64, dir) | ||
436 | __string(name, dentry->d_name.name) | ||
437 | ), | ||
438 | |||
439 | TP_fast_assign( | ||
440 | __entry->dev = dir->i_sb->s_dev; | ||
441 | __entry->dir = NFS_FILEID(dir); | ||
442 | __assign_str(name, dentry->d_name.name); | ||
443 | ), | ||
444 | |||
445 | TP_printk( | ||
446 | "name=%02x:%02x:%llu/%s", | ||
447 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
448 | (unsigned long long)__entry->dir, | ||
449 | __get_str(name) | ||
450 | ) | ||
451 | ); | ||
452 | |||
453 | #define DEFINE_NFS_DIRECTORY_EVENT(name) \ | ||
454 | DEFINE_EVENT(nfs_directory_event, name, \ | ||
455 | TP_PROTO( \ | ||
456 | const struct inode *dir, \ | ||
457 | const struct dentry *dentry \ | ||
458 | ), \ | ||
459 | TP_ARGS(dir, dentry)) | ||
460 | |||
461 | DECLARE_EVENT_CLASS(nfs_directory_event_done, | ||
462 | TP_PROTO( | ||
463 | const struct inode *dir, | ||
464 | const struct dentry *dentry, | ||
465 | int error | ||
466 | ), | ||
467 | |||
468 | TP_ARGS(dir, dentry, error), | ||
469 | |||
470 | TP_STRUCT__entry( | ||
471 | __field(int, error) | ||
472 | __field(dev_t, dev) | ||
473 | __field(u64, dir) | ||
474 | __string(name, dentry->d_name.name) | ||
475 | ), | ||
476 | |||
477 | TP_fast_assign( | ||
478 | __entry->dev = dir->i_sb->s_dev; | ||
479 | __entry->dir = NFS_FILEID(dir); | ||
480 | __entry->error = error; | ||
481 | __assign_str(name, dentry->d_name.name); | ||
482 | ), | ||
483 | |||
484 | TP_printk( | ||
485 | "error=%d name=%02x:%02x:%llu/%s", | ||
486 | __entry->error, | ||
487 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
488 | (unsigned long long)__entry->dir, | ||
489 | __get_str(name) | ||
490 | ) | ||
491 | ); | ||
492 | |||
493 | #define DEFINE_NFS_DIRECTORY_EVENT_DONE(name) \ | ||
494 | DEFINE_EVENT(nfs_directory_event_done, name, \ | ||
495 | TP_PROTO( \ | ||
496 | const struct inode *dir, \ | ||
497 | const struct dentry *dentry, \ | ||
498 | int error \ | ||
499 | ), \ | ||
500 | TP_ARGS(dir, dentry, error)) | ||
501 | |||
502 | DEFINE_NFS_DIRECTORY_EVENT(nfs_mknod_enter); | ||
503 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_mknod_exit); | ||
504 | DEFINE_NFS_DIRECTORY_EVENT(nfs_mkdir_enter); | ||
505 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_mkdir_exit); | ||
506 | DEFINE_NFS_DIRECTORY_EVENT(nfs_rmdir_enter); | ||
507 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_rmdir_exit); | ||
508 | DEFINE_NFS_DIRECTORY_EVENT(nfs_remove_enter); | ||
509 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_remove_exit); | ||
510 | DEFINE_NFS_DIRECTORY_EVENT(nfs_unlink_enter); | ||
511 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_unlink_exit); | ||
512 | DEFINE_NFS_DIRECTORY_EVENT(nfs_symlink_enter); | ||
513 | DEFINE_NFS_DIRECTORY_EVENT_DONE(nfs_symlink_exit); | ||
514 | |||
515 | TRACE_EVENT(nfs_link_enter, | ||
516 | TP_PROTO( | ||
517 | const struct inode *inode, | ||
518 | const struct inode *dir, | ||
519 | const struct dentry *dentry | ||
520 | ), | ||
521 | |||
522 | TP_ARGS(inode, dir, dentry), | ||
523 | |||
524 | TP_STRUCT__entry( | ||
525 | __field(dev_t, dev) | ||
526 | __field(u64, fileid) | ||
527 | __field(u64, dir) | ||
528 | __string(name, dentry->d_name.name) | ||
529 | ), | ||
530 | |||
531 | TP_fast_assign( | ||
532 | __entry->dev = inode->i_sb->s_dev; | ||
533 | __entry->fileid = NFS_FILEID(inode); | ||
534 | __entry->dir = NFS_FILEID(dir); | ||
535 | __assign_str(name, dentry->d_name.name); | ||
536 | ), | ||
537 | |||
538 | TP_printk( | ||
539 | "fileid=%02x:%02x:%llu name=%02x:%02x:%llu/%s", | ||
540 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
541 | __entry->fileid, | ||
542 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
543 | (unsigned long long)__entry->dir, | ||
544 | __get_str(name) | ||
545 | ) | ||
546 | ); | ||
547 | |||
548 | TRACE_EVENT(nfs_link_exit, | ||
549 | TP_PROTO( | ||
550 | const struct inode *inode, | ||
551 | const struct inode *dir, | ||
552 | const struct dentry *dentry, | ||
553 | int error | ||
554 | ), | ||
555 | |||
556 | TP_ARGS(inode, dir, dentry, error), | ||
557 | |||
558 | TP_STRUCT__entry( | ||
559 | __field(int, error) | ||
560 | __field(dev_t, dev) | ||
561 | __field(u64, fileid) | ||
562 | __field(u64, dir) | ||
563 | __string(name, dentry->d_name.name) | ||
564 | ), | ||
565 | |||
566 | TP_fast_assign( | ||
567 | __entry->dev = inode->i_sb->s_dev; | ||
568 | __entry->fileid = NFS_FILEID(inode); | ||
569 | __entry->dir = NFS_FILEID(dir); | ||
570 | __entry->error = error; | ||
571 | __assign_str(name, dentry->d_name.name); | ||
572 | ), | ||
573 | |||
574 | TP_printk( | ||
575 | "error=%d fileid=%02x:%02x:%llu name=%02x:%02x:%llu/%s", | ||
576 | __entry->error, | ||
577 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
578 | __entry->fileid, | ||
579 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
580 | (unsigned long long)__entry->dir, | ||
581 | __get_str(name) | ||
582 | ) | ||
583 | ); | ||
584 | |||
585 | DECLARE_EVENT_CLASS(nfs_rename_event, | ||
586 | TP_PROTO( | ||
587 | const struct inode *old_dir, | ||
588 | const struct dentry *old_dentry, | ||
589 | const struct inode *new_dir, | ||
590 | const struct dentry *new_dentry | ||
591 | ), | ||
592 | |||
593 | TP_ARGS(old_dir, old_dentry, new_dir, new_dentry), | ||
594 | |||
595 | TP_STRUCT__entry( | ||
596 | __field(dev_t, dev) | ||
597 | __field(u64, old_dir) | ||
598 | __field(u64, new_dir) | ||
599 | __string(old_name, old_dentry->d_name.name) | ||
600 | __string(new_name, new_dentry->d_name.name) | ||
601 | ), | ||
602 | |||
603 | TP_fast_assign( | ||
604 | __entry->dev = old_dir->i_sb->s_dev; | ||
605 | __entry->old_dir = NFS_FILEID(old_dir); | ||
606 | __entry->new_dir = NFS_FILEID(new_dir); | ||
607 | __assign_str(old_name, old_dentry->d_name.name); | ||
608 | __assign_str(new_name, new_dentry->d_name.name); | ||
609 | ), | ||
610 | |||
611 | TP_printk( | ||
612 | "old_name=%02x:%02x:%llu/%s new_name=%02x:%02x:%llu/%s", | ||
613 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
614 | (unsigned long long)__entry->old_dir, | ||
615 | __get_str(old_name), | ||
616 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
617 | (unsigned long long)__entry->new_dir, | ||
618 | __get_str(new_name) | ||
619 | ) | ||
620 | ); | ||
621 | #define DEFINE_NFS_RENAME_EVENT(name) \ | ||
622 | DEFINE_EVENT(nfs_rename_event, name, \ | ||
623 | TP_PROTO( \ | ||
624 | const struct inode *old_dir, \ | ||
625 | const struct dentry *old_dentry, \ | ||
626 | const struct inode *new_dir, \ | ||
627 | const struct dentry *new_dentry \ | ||
628 | ), \ | ||
629 | TP_ARGS(old_dir, old_dentry, new_dir, new_dentry)) | ||
630 | |||
631 | DECLARE_EVENT_CLASS(nfs_rename_event_done, | ||
632 | TP_PROTO( | ||
633 | const struct inode *old_dir, | ||
634 | const struct dentry *old_dentry, | ||
635 | const struct inode *new_dir, | ||
636 | const struct dentry *new_dentry, | ||
637 | int error | ||
638 | ), | ||
639 | |||
640 | TP_ARGS(old_dir, old_dentry, new_dir, new_dentry, error), | ||
641 | |||
642 | TP_STRUCT__entry( | ||
643 | __field(dev_t, dev) | ||
644 | __field(int, error) | ||
645 | __field(u64, old_dir) | ||
646 | __string(old_name, old_dentry->d_name.name) | ||
647 | __field(u64, new_dir) | ||
648 | __string(new_name, new_dentry->d_name.name) | ||
649 | ), | ||
650 | |||
651 | TP_fast_assign( | ||
652 | __entry->dev = old_dir->i_sb->s_dev; | ||
653 | __entry->old_dir = NFS_FILEID(old_dir); | ||
654 | __entry->new_dir = NFS_FILEID(new_dir); | ||
655 | __entry->error = error; | ||
656 | __assign_str(old_name, old_dentry->d_name.name); | ||
657 | __assign_str(new_name, new_dentry->d_name.name); | ||
658 | ), | ||
659 | |||
660 | TP_printk( | ||
661 | "error=%d old_name=%02x:%02x:%llu/%s " | ||
662 | "new_name=%02x:%02x:%llu/%s", | ||
663 | __entry->error, | ||
664 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
665 | (unsigned long long)__entry->old_dir, | ||
666 | __get_str(old_name), | ||
667 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
668 | (unsigned long long)__entry->new_dir, | ||
669 | __get_str(new_name) | ||
670 | ) | ||
671 | ); | ||
672 | #define DEFINE_NFS_RENAME_EVENT_DONE(name) \ | ||
673 | DEFINE_EVENT(nfs_rename_event_done, name, \ | ||
674 | TP_PROTO( \ | ||
675 | const struct inode *old_dir, \ | ||
676 | const struct dentry *old_dentry, \ | ||
677 | const struct inode *new_dir, \ | ||
678 | const struct dentry *new_dentry, \ | ||
679 | int error \ | ||
680 | ), \ | ||
681 | TP_ARGS(old_dir, old_dentry, new_dir, \ | ||
682 | new_dentry, error)) | ||
683 | |||
684 | DEFINE_NFS_RENAME_EVENT(nfs_rename_enter); | ||
685 | DEFINE_NFS_RENAME_EVENT_DONE(nfs_rename_exit); | ||
686 | |||
687 | DEFINE_NFS_RENAME_EVENT_DONE(nfs_sillyrename_rename); | ||
688 | |||
689 | TRACE_EVENT(nfs_sillyrename_unlink, | ||
690 | TP_PROTO( | ||
691 | const struct nfs_unlinkdata *data, | ||
692 | int error | ||
693 | ), | ||
694 | |||
695 | TP_ARGS(data, error), | ||
696 | |||
697 | TP_STRUCT__entry( | ||
698 | __field(dev_t, dev) | ||
699 | __field(int, error) | ||
700 | __field(u64, dir) | ||
701 | __dynamic_array(char, name, data->args.name.len + 1) | ||
702 | ), | ||
703 | |||
704 | TP_fast_assign( | ||
705 | struct inode *dir = data->dir; | ||
706 | size_t len = data->args.name.len; | ||
707 | __entry->dev = dir->i_sb->s_dev; | ||
708 | __entry->dir = NFS_FILEID(dir); | ||
709 | __entry->error = error; | ||
710 | memcpy(__get_dynamic_array(name), | ||
711 | data->args.name.name, len); | ||
712 | ((char *)__get_dynamic_array(name))[len] = 0; | ||
713 | ), | ||
714 | |||
715 | TP_printk( | ||
716 | "error=%d name=%02x:%02x:%llu/%s", | ||
717 | __entry->error, | ||
718 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
719 | (unsigned long long)__entry->dir, | ||
720 | __get_str(name) | ||
721 | ) | ||
722 | ); | ||
723 | #endif /* _TRACE_NFS_H */ | ||
724 | |||
725 | #undef TRACE_INCLUDE_PATH | ||
726 | #define TRACE_INCLUDE_PATH . | ||
727 | #define TRACE_INCLUDE_FILE nfstrace | ||
728 | /* This part must be outside protection */ | ||
729 | #include <trace/define_trace.h> | ||
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 29cfb7ade121..2ffebf2081ce 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -328,6 +328,19 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
328 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(nfs_pageio_init); | 329 | EXPORT_SYMBOL_GPL(nfs_pageio_init); |
330 | 330 | ||
331 | static bool nfs_match_open_context(const struct nfs_open_context *ctx1, | ||
332 | const struct nfs_open_context *ctx2) | ||
333 | { | ||
334 | return ctx1->cred == ctx2->cred && ctx1->state == ctx2->state; | ||
335 | } | ||
336 | |||
337 | static bool nfs_match_lock_context(const struct nfs_lock_context *l1, | ||
338 | const struct nfs_lock_context *l2) | ||
339 | { | ||
340 | return l1->lockowner.l_owner == l2->lockowner.l_owner | ||
341 | && l1->lockowner.l_pid == l2->lockowner.l_pid; | ||
342 | } | ||
343 | |||
331 | /** | 344 | /** |
332 | * nfs_can_coalesce_requests - test two requests for compatibility | 345 | * nfs_can_coalesce_requests - test two requests for compatibility |
333 | * @prev: pointer to nfs_page | 346 | * @prev: pointer to nfs_page |
@@ -343,13 +356,10 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, | |||
343 | struct nfs_page *req, | 356 | struct nfs_page *req, |
344 | struct nfs_pageio_descriptor *pgio) | 357 | struct nfs_pageio_descriptor *pgio) |
345 | { | 358 | { |
346 | if (req->wb_context->cred != prev->wb_context->cred) | 359 | if (!nfs_match_open_context(req->wb_context, prev->wb_context)) |
347 | return false; | ||
348 | if (req->wb_lock_context->lockowner.l_owner != prev->wb_lock_context->lockowner.l_owner) | ||
349 | return false; | ||
350 | if (req->wb_lock_context->lockowner.l_pid != prev->wb_lock_context->lockowner.l_pid) | ||
351 | return false; | 360 | return false; |
352 | if (req->wb_context->state != prev->wb_context->state) | 361 | if (req->wb_context->dentry->d_inode->i_flock != NULL && |
362 | !nfs_match_lock_context(req->wb_lock_context, prev->wb_lock_context)) | ||
353 | return false; | 363 | return false; |
354 | if (req->wb_pgbase != 0) | 364 | if (req->wb_pgbase != 0) |
355 | return false; | 365 | return false; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 3a3a79d6bf15..d75d938d36cb 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "internal.h" | 33 | #include "internal.h" |
34 | #include "pnfs.h" | 34 | #include "pnfs.h" |
35 | #include "iostat.h" | 35 | #include "iostat.h" |
36 | #include "nfs4trace.h" | ||
36 | 37 | ||
37 | #define NFSDBG_FACILITY NFSDBG_PNFS | 38 | #define NFSDBG_FACILITY NFSDBG_PNFS |
38 | #define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ) | 39 | #define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ) |
@@ -1526,6 +1527,7 @@ void pnfs_ld_write_done(struct nfs_write_data *data) | |||
1526 | { | 1527 | { |
1527 | struct nfs_pgio_header *hdr = data->header; | 1528 | struct nfs_pgio_header *hdr = data->header; |
1528 | 1529 | ||
1530 | trace_nfs4_pnfs_write(data, hdr->pnfs_error); | ||
1529 | if (!hdr->pnfs_error) { | 1531 | if (!hdr->pnfs_error) { |
1530 | pnfs_set_layoutcommit(data); | 1532 | pnfs_set_layoutcommit(data); |
1531 | hdr->mds_ops->rpc_call_done(&data->task, data); | 1533 | hdr->mds_ops->rpc_call_done(&data->task, data); |
@@ -1680,6 +1682,7 @@ void pnfs_ld_read_done(struct nfs_read_data *data) | |||
1680 | { | 1682 | { |
1681 | struct nfs_pgio_header *hdr = data->header; | 1683 | struct nfs_pgio_header *hdr = data->header; |
1682 | 1684 | ||
1685 | trace_nfs4_pnfs_read(data, hdr->pnfs_error); | ||
1683 | if (likely(!hdr->pnfs_error)) { | 1686 | if (likely(!hdr->pnfs_error)) { |
1684 | __nfs4_read_done_cb(data); | 1687 | __nfs4_read_done_cb(data); |
1685 | hdr->mds_ops->rpc_call_done(&data->task, data); | 1688 | hdr->mds_ops->rpc_call_done(&data->task, data); |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index c041c41f7a52..a8f57c728df5 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -623,9 +623,10 @@ static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message * | |||
623 | msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; | 623 | msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; |
624 | } | 624 | } |
625 | 625 | ||
626 | static void nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 626 | static int nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
627 | { | 627 | { |
628 | rpc_call_start(task); | 628 | rpc_call_start(task); |
629 | return 0; | ||
629 | } | 630 | } |
630 | 631 | ||
631 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 632 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -644,9 +645,10 @@ static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message | |||
644 | msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; | 645 | msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; |
645 | } | 646 | } |
646 | 647 | ||
647 | static void nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 648 | static int nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
648 | { | 649 | { |
649 | rpc_call_start(task); | 650 | rpc_call_start(task); |
651 | return 0; | ||
650 | } | 652 | } |
651 | 653 | ||
652 | static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 654 | static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 70a26c651f09..31db5c366b81 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -513,9 +513,10 @@ static void nfs_readpage_release_common(void *calldata) | |||
513 | void nfs_read_prepare(struct rpc_task *task, void *calldata) | 513 | void nfs_read_prepare(struct rpc_task *task, void *calldata) |
514 | { | 514 | { |
515 | struct nfs_read_data *data = calldata; | 515 | struct nfs_read_data *data = calldata; |
516 | NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); | 516 | int err; |
517 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | 517 | err = NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); |
518 | rpc_exit(task, -EIO); | 518 | if (err) |
519 | rpc_exit(task, err); | ||
519 | } | 520 | } |
520 | 521 | ||
521 | static const struct rpc_call_ops nfs_read_common_ops = { | 522 | static const struct rpc_call_ops nfs_read_common_ops = { |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index f6db66d8f647..5793f24613c8 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -923,7 +923,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) | |||
923 | data->nfs_server.port = NFS_UNSPEC_PORT; | 923 | data->nfs_server.port = NFS_UNSPEC_PORT; |
924 | data->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 924 | data->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
925 | data->auth_flavors[0] = RPC_AUTH_MAXFLAVOR; | 925 | data->auth_flavors[0] = RPC_AUTH_MAXFLAVOR; |
926 | data->auth_flavor_len = 1; | 926 | data->auth_flavor_len = 0; |
927 | data->minorversion = 0; | 927 | data->minorversion = 0; |
928 | data->need_mount = true; | 928 | data->need_mount = true; |
929 | data->net = current->nsproxy->net_ns; | 929 | data->net = current->nsproxy->net_ns; |
@@ -1018,6 +1018,13 @@ static void nfs_set_mount_transport_protocol(struct nfs_parsed_mount_data *mnt) | |||
1018 | } | 1018 | } |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | static void nfs_set_auth_parsed_mount_data(struct nfs_parsed_mount_data *data, | ||
1022 | rpc_authflavor_t pseudoflavor) | ||
1023 | { | ||
1024 | data->auth_flavors[0] = pseudoflavor; | ||
1025 | data->auth_flavor_len = 1; | ||
1026 | } | ||
1027 | |||
1021 | /* | 1028 | /* |
1022 | * Parse the value of the 'sec=' option. | 1029 | * Parse the value of the 'sec=' option. |
1023 | */ | 1030 | */ |
@@ -1025,49 +1032,50 @@ static int nfs_parse_security_flavors(char *value, | |||
1025 | struct nfs_parsed_mount_data *mnt) | 1032 | struct nfs_parsed_mount_data *mnt) |
1026 | { | 1033 | { |
1027 | substring_t args[MAX_OPT_ARGS]; | 1034 | substring_t args[MAX_OPT_ARGS]; |
1035 | rpc_authflavor_t pseudoflavor; | ||
1028 | 1036 | ||
1029 | dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value); | 1037 | dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value); |
1030 | 1038 | ||
1031 | switch (match_token(value, nfs_secflavor_tokens, args)) { | 1039 | switch (match_token(value, nfs_secflavor_tokens, args)) { |
1032 | case Opt_sec_none: | 1040 | case Opt_sec_none: |
1033 | mnt->auth_flavors[0] = RPC_AUTH_NULL; | 1041 | pseudoflavor = RPC_AUTH_NULL; |
1034 | break; | 1042 | break; |
1035 | case Opt_sec_sys: | 1043 | case Opt_sec_sys: |
1036 | mnt->auth_flavors[0] = RPC_AUTH_UNIX; | 1044 | pseudoflavor = RPC_AUTH_UNIX; |
1037 | break; | 1045 | break; |
1038 | case Opt_sec_krb5: | 1046 | case Opt_sec_krb5: |
1039 | mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5; | 1047 | pseudoflavor = RPC_AUTH_GSS_KRB5; |
1040 | break; | 1048 | break; |
1041 | case Opt_sec_krb5i: | 1049 | case Opt_sec_krb5i: |
1042 | mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I; | 1050 | pseudoflavor = RPC_AUTH_GSS_KRB5I; |
1043 | break; | 1051 | break; |
1044 | case Opt_sec_krb5p: | 1052 | case Opt_sec_krb5p: |
1045 | mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P; | 1053 | pseudoflavor = RPC_AUTH_GSS_KRB5P; |
1046 | break; | 1054 | break; |
1047 | case Opt_sec_lkey: | 1055 | case Opt_sec_lkey: |
1048 | mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY; | 1056 | pseudoflavor = RPC_AUTH_GSS_LKEY; |
1049 | break; | 1057 | break; |
1050 | case Opt_sec_lkeyi: | 1058 | case Opt_sec_lkeyi: |
1051 | mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI; | 1059 | pseudoflavor = RPC_AUTH_GSS_LKEYI; |
1052 | break; | 1060 | break; |
1053 | case Opt_sec_lkeyp: | 1061 | case Opt_sec_lkeyp: |
1054 | mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP; | 1062 | pseudoflavor = RPC_AUTH_GSS_LKEYP; |
1055 | break; | 1063 | break; |
1056 | case Opt_sec_spkm: | 1064 | case Opt_sec_spkm: |
1057 | mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM; | 1065 | pseudoflavor = RPC_AUTH_GSS_SPKM; |
1058 | break; | 1066 | break; |
1059 | case Opt_sec_spkmi: | 1067 | case Opt_sec_spkmi: |
1060 | mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI; | 1068 | pseudoflavor = RPC_AUTH_GSS_SPKMI; |
1061 | break; | 1069 | break; |
1062 | case Opt_sec_spkmp: | 1070 | case Opt_sec_spkmp: |
1063 | mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP; | 1071 | pseudoflavor = RPC_AUTH_GSS_SPKMP; |
1064 | break; | 1072 | break; |
1065 | default: | 1073 | default: |
1066 | return 0; | 1074 | return 0; |
1067 | } | 1075 | } |
1068 | 1076 | ||
1069 | mnt->flags |= NFS_MOUNT_SECFLAVOUR; | 1077 | mnt->flags |= NFS_MOUNT_SECFLAVOUR; |
1070 | mnt->auth_flavor_len = 1; | 1078 | nfs_set_auth_parsed_mount_data(mnt, pseudoflavor); |
1071 | return 1; | 1079 | return 1; |
1072 | } | 1080 | } |
1073 | 1081 | ||
@@ -1729,7 +1737,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf | |||
1729 | * Was a sec= authflavor specified in the options? First, verify | 1737 | * Was a sec= authflavor specified in the options? First, verify |
1730 | * whether the server supports it, and then just try to use it if so. | 1738 | * whether the server supports it, and then just try to use it if so. |
1731 | */ | 1739 | */ |
1732 | if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR) { | 1740 | if (args->auth_flavor_len > 0) { |
1733 | status = nfs_verify_authflavor(args, authlist, authlist_len); | 1741 | status = nfs_verify_authflavor(args, authlist, authlist_len); |
1734 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); | 1742 | dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); |
1735 | if (status) | 1743 | if (status) |
@@ -1760,7 +1768,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf | |||
1760 | /* Fallthrough */ | 1768 | /* Fallthrough */ |
1761 | } | 1769 | } |
1762 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); | 1770 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); |
1763 | args->auth_flavors[0] = flavor; | 1771 | nfs_set_auth_parsed_mount_data(args, flavor); |
1764 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | 1772 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); |
1765 | if (!IS_ERR(server)) | 1773 | if (!IS_ERR(server)) |
1766 | return server; | 1774 | return server; |
@@ -1776,7 +1784,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf | |||
1776 | 1784 | ||
1777 | /* Last chance! Try AUTH_UNIX */ | 1785 | /* Last chance! Try AUTH_UNIX */ |
1778 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); | 1786 | dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); |
1779 | args->auth_flavors[0] = RPC_AUTH_UNIX; | 1787 | nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); |
1780 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); | 1788 | return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); |
1781 | } | 1789 | } |
1782 | 1790 | ||
@@ -1893,6 +1901,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1893 | { | 1901 | { |
1894 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; | 1902 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1895 | struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address; | 1903 | struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address; |
1904 | int extra_flags = NFS_MOUNT_LEGACY_INTERFACE; | ||
1896 | 1905 | ||
1897 | if (data == NULL) | 1906 | if (data == NULL) |
1898 | goto out_no_data; | 1907 | goto out_no_data; |
@@ -1908,6 +1917,8 @@ static int nfs23_validate_mount_data(void *options, | |||
1908 | goto out_no_v3; | 1917 | goto out_no_v3; |
1909 | data->root.size = NFS2_FHSIZE; | 1918 | data->root.size = NFS2_FHSIZE; |
1910 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | 1919 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); |
1920 | /* Turn off security negotiation */ | ||
1921 | extra_flags |= NFS_MOUNT_SECFLAVOUR; | ||
1911 | case 4: | 1922 | case 4: |
1912 | if (data->flags & NFS_MOUNT_SECFLAVOUR) | 1923 | if (data->flags & NFS_MOUNT_SECFLAVOUR) |
1913 | goto out_no_sec; | 1924 | goto out_no_sec; |
@@ -1935,7 +1946,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1935 | * can deal with. | 1946 | * can deal with. |
1936 | */ | 1947 | */ |
1937 | args->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1948 | args->flags = data->flags & NFS_MOUNT_FLAGMASK; |
1938 | args->flags |= NFS_MOUNT_LEGACY_INTERFACE; | 1949 | args->flags |= extra_flags; |
1939 | args->rsize = data->rsize; | 1950 | args->rsize = data->rsize; |
1940 | args->wsize = data->wsize; | 1951 | args->wsize = data->wsize; |
1941 | args->timeo = data->timeo; | 1952 | args->timeo = data->timeo; |
@@ -1959,9 +1970,10 @@ static int nfs23_validate_mount_data(void *options, | |||
1959 | args->namlen = data->namlen; | 1970 | args->namlen = data->namlen; |
1960 | args->bsize = data->bsize; | 1971 | args->bsize = data->bsize; |
1961 | 1972 | ||
1962 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
1963 | if (data->flags & NFS_MOUNT_SECFLAVOUR) | 1973 | if (data->flags & NFS_MOUNT_SECFLAVOUR) |
1964 | args->auth_flavors[0] = data->pseudoflavor; | 1974 | nfs_set_auth_parsed_mount_data(args, data->pseudoflavor); |
1975 | else | ||
1976 | nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); | ||
1965 | if (!args->nfs_server.hostname) | 1977 | if (!args->nfs_server.hostname) |
1966 | goto out_nomem; | 1978 | goto out_nomem; |
1967 | 1979 | ||
@@ -2084,6 +2096,8 @@ static int nfs_validate_text_mount_data(void *options, | |||
2084 | max_namelen = NFS4_MAXNAMLEN; | 2096 | max_namelen = NFS4_MAXNAMLEN; |
2085 | max_pathlen = NFS4_MAXPATHLEN; | 2097 | max_pathlen = NFS4_MAXPATHLEN; |
2086 | nfs_validate_transport_protocol(args); | 2098 | nfs_validate_transport_protocol(args); |
2099 | if (args->nfs_server.protocol == XPRT_TRANSPORT_UDP) | ||
2100 | goto out_invalid_transport_udp; | ||
2087 | nfs4_validate_mount_flags(args); | 2101 | nfs4_validate_mount_flags(args); |
2088 | #else | 2102 | #else |
2089 | goto out_v4_not_compiled; | 2103 | goto out_v4_not_compiled; |
@@ -2106,6 +2120,10 @@ static int nfs_validate_text_mount_data(void *options, | |||
2106 | out_v4_not_compiled: | 2120 | out_v4_not_compiled: |
2107 | dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n"); | 2121 | dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n"); |
2108 | return -EPROTONOSUPPORT; | 2122 | return -EPROTONOSUPPORT; |
2123 | #else | ||
2124 | out_invalid_transport_udp: | ||
2125 | dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n"); | ||
2126 | return -EINVAL; | ||
2109 | #endif /* !CONFIG_NFS_V4 */ | 2127 | #endif /* !CONFIG_NFS_V4 */ |
2110 | 2128 | ||
2111 | out_no_address: | 2129 | out_no_address: |
@@ -2170,7 +2188,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
2170 | data->rsize = nfss->rsize; | 2188 | data->rsize = nfss->rsize; |
2171 | data->wsize = nfss->wsize; | 2189 | data->wsize = nfss->wsize; |
2172 | data->retrans = nfss->client->cl_timeout->to_retries; | 2190 | data->retrans = nfss->client->cl_timeout->to_retries; |
2173 | data->auth_flavors[0] = nfss->client->cl_auth->au_flavor; | 2191 | nfs_set_auth_parsed_mount_data(data, nfss->client->cl_auth->au_flavor); |
2174 | data->acregmin = nfss->acregmin / HZ; | 2192 | data->acregmin = nfss->acregmin / HZ; |
2175 | data->acregmax = nfss->acregmax / HZ; | 2193 | data->acregmax = nfss->acregmax / HZ; |
2176 | data->acdirmin = nfss->acdirmin / HZ; | 2194 | data->acdirmin = nfss->acdirmin / HZ; |
@@ -2277,6 +2295,18 @@ void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) | |||
2277 | nfs_initialise_sb(sb); | 2295 | nfs_initialise_sb(sb); |
2278 | } | 2296 | } |
2279 | 2297 | ||
2298 | #define NFS_MOUNT_CMP_FLAGMASK ~(NFS_MOUNT_INTR \ | ||
2299 | | NFS_MOUNT_SECURE \ | ||
2300 | | NFS_MOUNT_TCP \ | ||
2301 | | NFS_MOUNT_VER3 \ | ||
2302 | | NFS_MOUNT_KERBEROS \ | ||
2303 | | NFS_MOUNT_NONLM \ | ||
2304 | | NFS_MOUNT_BROKEN_SUID \ | ||
2305 | | NFS_MOUNT_STRICTLOCK \ | ||
2306 | | NFS_MOUNT_UNSHARED \ | ||
2307 | | NFS_MOUNT_NORESVPORT \ | ||
2308 | | NFS_MOUNT_LEGACY_INTERFACE) | ||
2309 | |||
2280 | static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags) | 2310 | static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags) |
2281 | { | 2311 | { |
2282 | const struct nfs_server *a = s->s_fs_info; | 2312 | const struct nfs_server *a = s->s_fs_info; |
@@ -2287,7 +2317,7 @@ static int nfs_compare_mount_options(const struct super_block *s, const struct n | |||
2287 | goto Ebusy; | 2317 | goto Ebusy; |
2288 | if (a->nfs_client != b->nfs_client) | 2318 | if (a->nfs_client != b->nfs_client) |
2289 | goto Ebusy; | 2319 | goto Ebusy; |
2290 | if (a->flags != b->flags) | 2320 | if ((a->flags ^ b->flags) & NFS_MOUNT_CMP_FLAGMASK) |
2291 | goto Ebusy; | 2321 | goto Ebusy; |
2292 | if (a->wsize != b->wsize) | 2322 | if (a->wsize != b->wsize) |
2293 | goto Ebusy; | 2323 | goto Ebusy; |
@@ -2301,7 +2331,8 @@ static int nfs_compare_mount_options(const struct super_block *s, const struct n | |||
2301 | goto Ebusy; | 2331 | goto Ebusy; |
2302 | if (a->acdirmax != b->acdirmax) | 2332 | if (a->acdirmax != b->acdirmax) |
2303 | goto Ebusy; | 2333 | goto Ebusy; |
2304 | if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor) | 2334 | if (b->flags & NFS_MOUNT_SECFLAVOUR && |
2335 | clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor) | ||
2305 | goto Ebusy; | 2336 | goto Ebusy; |
2306 | return 1; | 2337 | return 1; |
2307 | Ebusy: | 2338 | Ebusy: |
@@ -2673,15 +2704,17 @@ static int nfs4_validate_mount_data(void *options, | |||
2673 | goto out_no_address; | 2704 | goto out_no_address; |
2674 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); | 2705 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); |
2675 | 2706 | ||
2676 | args->auth_flavors[0] = RPC_AUTH_UNIX; | ||
2677 | if (data->auth_flavourlen) { | 2707 | if (data->auth_flavourlen) { |
2708 | rpc_authflavor_t pseudoflavor; | ||
2678 | if (data->auth_flavourlen > 1) | 2709 | if (data->auth_flavourlen > 1) |
2679 | goto out_inval_auth; | 2710 | goto out_inval_auth; |
2680 | if (copy_from_user(&args->auth_flavors[0], | 2711 | if (copy_from_user(&pseudoflavor, |
2681 | data->auth_flavours, | 2712 | data->auth_flavours, |
2682 | sizeof(args->auth_flavors[0]))) | 2713 | sizeof(pseudoflavor))) |
2683 | return -EFAULT; | 2714 | return -EFAULT; |
2684 | } | 2715 | nfs_set_auth_parsed_mount_data(args, pseudoflavor); |
2716 | } else | ||
2717 | nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); | ||
2685 | 2718 | ||
2686 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); | 2719 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); |
2687 | if (IS_ERR(c)) | 2720 | if (IS_ERR(c)) |
@@ -2715,6 +2748,8 @@ static int nfs4_validate_mount_data(void *options, | |||
2715 | args->acdirmax = data->acdirmax; | 2748 | args->acdirmax = data->acdirmax; |
2716 | args->nfs_server.protocol = data->proto; | 2749 | args->nfs_server.protocol = data->proto; |
2717 | nfs_validate_transport_protocol(args); | 2750 | nfs_validate_transport_protocol(args); |
2751 | if (args->nfs_server.protocol == XPRT_TRANSPORT_UDP) | ||
2752 | goto out_invalid_transport_udp; | ||
2718 | 2753 | ||
2719 | break; | 2754 | break; |
2720 | default: | 2755 | default: |
@@ -2735,6 +2770,10 @@ out_inval_auth: | |||
2735 | out_no_address: | 2770 | out_no_address: |
2736 | dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); | 2771 | dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); |
2737 | return -EINVAL; | 2772 | return -EINVAL; |
2773 | |||
2774 | out_invalid_transport_udp: | ||
2775 | dfprintk(MOUNT, "NFSv4: Unsupported transport protocol udp\n"); | ||
2776 | return -EINVAL; | ||
2738 | } | 2777 | } |
2739 | 2778 | ||
2740 | /* | 2779 | /* |
@@ -2750,6 +2789,7 @@ bool nfs4_disable_idmapping = true; | |||
2750 | unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; | 2789 | unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; |
2751 | unsigned short send_implementation_id = 1; | 2790 | unsigned short send_implementation_id = 1; |
2752 | char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN] = ""; | 2791 | char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN] = ""; |
2792 | bool recover_lost_locks = false; | ||
2753 | 2793 | ||
2754 | EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport); | 2794 | EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport); |
2755 | EXPORT_SYMBOL_GPL(nfs_callback_tcpport); | 2795 | EXPORT_SYMBOL_GPL(nfs_callback_tcpport); |
@@ -2758,6 +2798,7 @@ EXPORT_SYMBOL_GPL(nfs4_disable_idmapping); | |||
2758 | EXPORT_SYMBOL_GPL(max_session_slots); | 2798 | EXPORT_SYMBOL_GPL(max_session_slots); |
2759 | EXPORT_SYMBOL_GPL(send_implementation_id); | 2799 | EXPORT_SYMBOL_GPL(send_implementation_id); |
2760 | EXPORT_SYMBOL_GPL(nfs4_client_id_uniquifier); | 2800 | EXPORT_SYMBOL_GPL(nfs4_client_id_uniquifier); |
2801 | EXPORT_SYMBOL_GPL(recover_lost_locks); | ||
2761 | 2802 | ||
2762 | #define NFS_CALLBACK_MAXPORTNR (65535U) | 2803 | #define NFS_CALLBACK_MAXPORTNR (65535U) |
2763 | 2804 | ||
@@ -2795,4 +2836,10 @@ MODULE_PARM_DESC(send_implementation_id, | |||
2795 | "Send implementation ID with NFSv4.1 exchange_id"); | 2836 | "Send implementation ID with NFSv4.1 exchange_id"); |
2796 | MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string"); | 2837 | MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string"); |
2797 | 2838 | ||
2839 | module_param(recover_lost_locks, bool, 0644); | ||
2840 | MODULE_PARM_DESC(recover_lost_locks, | ||
2841 | "If the server reports that a lock might be lost, " | ||
2842 | "try to recover it risking data corruption."); | ||
2843 | |||
2844 | |||
2798 | #endif /* CONFIG_NFS_V4 */ | 2845 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 60395ad3a2e4..bb939edd4c99 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include "iostat.h" | 20 | #include "iostat.h" |
21 | #include "delegation.h" | 21 | #include "delegation.h" |
22 | 22 | ||
23 | #include "nfstrace.h" | ||
24 | |||
23 | /** | 25 | /** |
24 | * nfs_free_unlinkdata - release data from a sillydelete operation. | 26 | * nfs_free_unlinkdata - release data from a sillydelete operation. |
25 | * @data: pointer to unlink structure. | 27 | * @data: pointer to unlink structure. |
@@ -77,6 +79,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) | |||
77 | struct nfs_unlinkdata *data = calldata; | 79 | struct nfs_unlinkdata *data = calldata; |
78 | struct inode *dir = data->dir; | 80 | struct inode *dir = data->dir; |
79 | 81 | ||
82 | trace_nfs_sillyrename_unlink(data, task->tk_status); | ||
80 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) | 83 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) |
81 | rpc_restart_call_prepare(task); | 84 | rpc_restart_call_prepare(task); |
82 | } | 85 | } |
@@ -204,6 +207,13 @@ out_free: | |||
204 | return ret; | 207 | return ret; |
205 | } | 208 | } |
206 | 209 | ||
210 | void nfs_wait_on_sillyrename(struct dentry *dentry) | ||
211 | { | ||
212 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); | ||
213 | |||
214 | wait_event(nfsi->waitqueue, atomic_read(&nfsi->silly_count) <= 1); | ||
215 | } | ||
216 | |||
207 | void nfs_block_sillyrename(struct dentry *dentry) | 217 | void nfs_block_sillyrename(struct dentry *dentry) |
208 | { | 218 | { |
209 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); | 219 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); |
@@ -336,6 +346,8 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata) | |||
336 | struct inode *new_dir = data->new_dir; | 346 | struct inode *new_dir = data->new_dir; |
337 | struct dentry *old_dentry = data->old_dentry; | 347 | struct dentry *old_dentry = data->old_dentry; |
338 | 348 | ||
349 | trace_nfs_sillyrename_rename(old_dir, old_dentry, | ||
350 | new_dir, data->new_dentry, task->tk_status); | ||
339 | if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) { | 351 | if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) { |
340 | rpc_restart_call_prepare(task); | 352 | rpc_restart_call_prepare(task); |
341 | return; | 353 | return; |
@@ -444,6 +456,14 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir, | |||
444 | return rpc_run_task(&task_setup_data); | 456 | return rpc_run_task(&task_setup_data); |
445 | } | 457 | } |
446 | 458 | ||
459 | #define SILLYNAME_PREFIX ".nfs" | ||
460 | #define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1) | ||
461 | #define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1) | ||
462 | #define SILLYNAME_COUNTER_LEN ((unsigned)sizeof(unsigned int) << 1) | ||
463 | #define SILLYNAME_LEN (SILLYNAME_PREFIX_LEN + \ | ||
464 | SILLYNAME_FILEID_LEN + \ | ||
465 | SILLYNAME_COUNTER_LEN) | ||
466 | |||
447 | /** | 467 | /** |
448 | * nfs_sillyrename - Perform a silly-rename of a dentry | 468 | * nfs_sillyrename - Perform a silly-rename of a dentry |
449 | * @dir: inode of directory that contains dentry | 469 | * @dir: inode of directory that contains dentry |
@@ -469,10 +489,8 @@ int | |||
469 | nfs_sillyrename(struct inode *dir, struct dentry *dentry) | 489 | nfs_sillyrename(struct inode *dir, struct dentry *dentry) |
470 | { | 490 | { |
471 | static unsigned int sillycounter; | 491 | static unsigned int sillycounter; |
472 | const int fileidsize = sizeof(NFS_FILEID(dentry->d_inode))*2; | 492 | unsigned char silly[SILLYNAME_LEN + 1]; |
473 | const int countersize = sizeof(sillycounter)*2; | 493 | unsigned long long fileid; |
474 | const int slen = sizeof(".nfs")+fileidsize+countersize-1; | ||
475 | char silly[slen+1]; | ||
476 | struct dentry *sdentry; | 494 | struct dentry *sdentry; |
477 | struct rpc_task *task; | 495 | struct rpc_task *task; |
478 | int error = -EIO; | 496 | int error = -EIO; |
@@ -489,20 +507,20 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
489 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | 507 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) |
490 | goto out; | 508 | goto out; |
491 | 509 | ||
492 | sprintf(silly, ".nfs%*.*Lx", | 510 | fileid = NFS_FILEID(dentry->d_inode); |
493 | fileidsize, fileidsize, | ||
494 | (unsigned long long)NFS_FILEID(dentry->d_inode)); | ||
495 | 511 | ||
496 | /* Return delegation in anticipation of the rename */ | 512 | /* Return delegation in anticipation of the rename */ |
497 | NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode); | 513 | NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode); |
498 | 514 | ||
499 | sdentry = NULL; | 515 | sdentry = NULL; |
500 | do { | 516 | do { |
501 | char *suffix = silly + slen - countersize; | 517 | int slen; |
502 | |||
503 | dput(sdentry); | 518 | dput(sdentry); |
504 | sillycounter++; | 519 | sillycounter++; |
505 | sprintf(suffix, "%*.*x", countersize, countersize, sillycounter); | 520 | slen = scnprintf(silly, sizeof(silly), |
521 | SILLYNAME_PREFIX "%0*llx%0*x", | ||
522 | SILLYNAME_FILEID_LEN, fileid, | ||
523 | SILLYNAME_COUNTER_LEN, sillycounter); | ||
506 | 524 | ||
507 | dfprintk(VFS, "NFS: trying to rename %s to %s\n", | 525 | dfprintk(VFS, "NFS: trying to rename %s to %s\n", |
508 | dentry->d_name.name, silly); | 526 | dentry->d_name.name, silly); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f1bdb7254776..ac1dc331ba31 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include "fscache.h" | 31 | #include "fscache.h" |
32 | #include "pnfs.h" | 32 | #include "pnfs.h" |
33 | 33 | ||
34 | #include "nfstrace.h" | ||
35 | |||
34 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 36 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
35 | 37 | ||
36 | #define MIN_POOL_WRITE (32) | 38 | #define MIN_POOL_WRITE (32) |
@@ -861,7 +863,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
861 | return 0; | 863 | return 0; |
862 | l_ctx = req->wb_lock_context; | 864 | l_ctx = req->wb_lock_context; |
863 | do_flush = req->wb_page != page || req->wb_context != ctx; | 865 | do_flush = req->wb_page != page || req->wb_context != ctx; |
864 | if (l_ctx) { | 866 | if (l_ctx && ctx->dentry->d_inode->i_flock != NULL) { |
865 | do_flush |= l_ctx->lockowner.l_owner != current->files | 867 | do_flush |= l_ctx->lockowner.l_owner != current->files |
866 | || l_ctx->lockowner.l_pid != current->tgid; | 868 | || l_ctx->lockowner.l_pid != current->tgid; |
867 | } | 869 | } |
@@ -874,6 +876,33 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
874 | } | 876 | } |
875 | 877 | ||
876 | /* | 878 | /* |
879 | * Avoid buffered writes when a open context credential's key would | ||
880 | * expire soon. | ||
881 | * | ||
882 | * Returns -EACCES if the key will expire within RPC_KEY_EXPIRE_FAIL. | ||
883 | * | ||
884 | * Return 0 and set a credential flag which triggers the inode to flush | ||
885 | * and performs NFS_FILE_SYNC writes if the key will expired within | ||
886 | * RPC_KEY_EXPIRE_TIMEO. | ||
887 | */ | ||
888 | int | ||
889 | nfs_key_timeout_notify(struct file *filp, struct inode *inode) | ||
890 | { | ||
891 | struct nfs_open_context *ctx = nfs_file_open_context(filp); | ||
892 | struct rpc_auth *auth = NFS_SERVER(inode)->client->cl_auth; | ||
893 | |||
894 | return rpcauth_key_timeout_notify(auth, ctx->cred); | ||
895 | } | ||
896 | |||
897 | /* | ||
898 | * Test if the open context credential key is marked to expire soon. | ||
899 | */ | ||
900 | bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx) | ||
901 | { | ||
902 | return rpcauth_cred_key_to_expire(ctx->cred); | ||
903 | } | ||
904 | |||
905 | /* | ||
877 | * If the page cache is marked as unsafe or invalid, then we can't rely on | 906 | * If the page cache is marked as unsafe or invalid, then we can't rely on |
878 | * the PageUptodate() flag. In this case, we will need to turn off | 907 | * the PageUptodate() flag. In this case, we will need to turn off |
879 | * write optimisations that depend on the page contents being correct. | 908 | * write optimisations that depend on the page contents being correct. |
@@ -993,6 +1022,9 @@ int nfs_initiate_write(struct rpc_clnt *clnt, | |||
993 | data->args.count, | 1022 | data->args.count, |
994 | (unsigned long long)data->args.offset); | 1023 | (unsigned long long)data->args.offset); |
995 | 1024 | ||
1025 | nfs4_state_protect_write(NFS_SERVER(inode)->nfs_client, | ||
1026 | &task_setup_data.rpc_client, &msg, data); | ||
1027 | |||
996 | task = rpc_run_task(&task_setup_data); | 1028 | task = rpc_run_task(&task_setup_data); |
997 | if (IS_ERR(task)) { | 1029 | if (IS_ERR(task)) { |
998 | ret = PTR_ERR(task); | 1030 | ret = PTR_ERR(task); |
@@ -1265,9 +1297,10 @@ EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); | |||
1265 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1297 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |
1266 | { | 1298 | { |
1267 | struct nfs_write_data *data = calldata; | 1299 | struct nfs_write_data *data = calldata; |
1268 | NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data); | 1300 | int err; |
1269 | if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags))) | 1301 | err = NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data); |
1270 | rpc_exit(task, -EIO); | 1302 | if (err) |
1303 | rpc_exit(task, err); | ||
1271 | } | 1304 | } |
1272 | 1305 | ||
1273 | void nfs_commit_prepare(struct rpc_task *task, void *calldata) | 1306 | void nfs_commit_prepare(struct rpc_task *task, void *calldata) |
@@ -1458,6 +1491,9 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data, | |||
1458 | 1491 | ||
1459 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 1492 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
1460 | 1493 | ||
1494 | nfs4_state_protect(NFS_SERVER(data->inode)->nfs_client, | ||
1495 | NFS_SP4_MACH_CRED_COMMIT, &task_setup_data.rpc_client, &msg); | ||
1496 | |||
1461 | task = rpc_run_task(&task_setup_data); | 1497 | task = rpc_run_task(&task_setup_data); |
1462 | if (IS_ERR(task)) | 1498 | if (IS_ERR(task)) |
1463 | return PTR_ERR(task); | 1499 | return PTR_ERR(task); |
@@ -1732,8 +1768,14 @@ int nfs_wb_all(struct inode *inode) | |||
1732 | .range_start = 0, | 1768 | .range_start = 0, |
1733 | .range_end = LLONG_MAX, | 1769 | .range_end = LLONG_MAX, |
1734 | }; | 1770 | }; |
1771 | int ret; | ||
1735 | 1772 | ||
1736 | return sync_inode(inode, &wbc); | 1773 | trace_nfs_writeback_inode_enter(inode); |
1774 | |||
1775 | ret = sync_inode(inode, &wbc); | ||
1776 | |||
1777 | trace_nfs_writeback_inode_exit(inode, ret); | ||
1778 | return ret; | ||
1737 | } | 1779 | } |
1738 | EXPORT_SYMBOL_GPL(nfs_wb_all); | 1780 | EXPORT_SYMBOL_GPL(nfs_wb_all); |
1739 | 1781 | ||
@@ -1781,6 +1823,8 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
1781 | }; | 1823 | }; |
1782 | int ret; | 1824 | int ret; |
1783 | 1825 | ||
1826 | trace_nfs_writeback_page_enter(inode); | ||
1827 | |||
1784 | for (;;) { | 1828 | for (;;) { |
1785 | wait_on_page_writeback(page); | 1829 | wait_on_page_writeback(page); |
1786 | if (clear_page_dirty_for_io(page)) { | 1830 | if (clear_page_dirty_for_io(page)) { |
@@ -1789,14 +1833,15 @@ int nfs_wb_page(struct inode *inode, struct page *page) | |||
1789 | goto out_error; | 1833 | goto out_error; |
1790 | continue; | 1834 | continue; |
1791 | } | 1835 | } |
1836 | ret = 0; | ||
1792 | if (!PagePrivate(page)) | 1837 | if (!PagePrivate(page)) |
1793 | break; | 1838 | break; |
1794 | ret = nfs_commit_inode(inode, FLUSH_SYNC); | 1839 | ret = nfs_commit_inode(inode, FLUSH_SYNC); |
1795 | if (ret < 0) | 1840 | if (ret < 0) |
1796 | goto out_error; | 1841 | goto out_error; |
1797 | } | 1842 | } |
1798 | return 0; | ||
1799 | out_error: | 1843 | out_error: |
1844 | trace_nfs_writeback_page_exit(inode, ret); | ||
1800 | return ret; | 1845 | return ret; |
1801 | } | 1846 | } |
1802 | 1847 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7125cef74164..3ea4cde8701c 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -524,6 +524,7 @@ static inline void nfs4_label_free(void *label) {} | |||
524 | * linux/fs/nfs/unlink.c | 524 | * linux/fs/nfs/unlink.c |
525 | */ | 525 | */ |
526 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); | 526 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); |
527 | extern void nfs_wait_on_sillyrename(struct dentry *dentry); | ||
527 | extern void nfs_block_sillyrename(struct dentry *dentry); | 528 | extern void nfs_block_sillyrename(struct dentry *dentry); |
528 | extern void nfs_unblock_sillyrename(struct dentry *dentry); | 529 | extern void nfs_unblock_sillyrename(struct dentry *dentry); |
529 | extern int nfs_sillyrename(struct inode *dir, struct dentry *dentry); | 530 | extern int nfs_sillyrename(struct inode *dir, struct dentry *dentry); |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index d2212432c456..b8cedced50c9 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -56,6 +56,7 @@ struct nfs_client { | |||
56 | struct rpc_cred *cl_machine_cred; | 56 | struct rpc_cred *cl_machine_cred; |
57 | 57 | ||
58 | #if IS_ENABLED(CONFIG_NFS_V4) | 58 | #if IS_ENABLED(CONFIG_NFS_V4) |
59 | struct list_head cl_ds_clients; /* auth flavor data servers */ | ||
59 | u64 cl_clientid; /* constant */ | 60 | u64 cl_clientid; /* constant */ |
60 | nfs4_verifier cl_confirm; /* Clientid verifier */ | 61 | nfs4_verifier cl_confirm; /* Clientid verifier */ |
61 | unsigned long cl_state; | 62 | unsigned long cl_state; |
@@ -78,6 +79,9 @@ struct nfs_client { | |||
78 | u32 cl_cb_ident; /* v4.0 callback identifier */ | 79 | u32 cl_cb_ident; /* v4.0 callback identifier */ |
79 | const struct nfs4_minor_version_ops *cl_mvops; | 80 | const struct nfs4_minor_version_ops *cl_mvops; |
80 | 81 | ||
82 | /* NFSv4.0 transport blocking */ | ||
83 | struct nfs4_slot_table *cl_slot_tbl; | ||
84 | |||
81 | /* The sequence id to use for the next CREATE_SESSION */ | 85 | /* The sequence id to use for the next CREATE_SESSION */ |
82 | u32 cl_seqid; | 86 | u32 cl_seqid; |
83 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ | 87 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ |
@@ -87,6 +91,15 @@ struct nfs_client { | |||
87 | struct nfs41_server_owner *cl_serverowner; | 91 | struct nfs41_server_owner *cl_serverowner; |
88 | struct nfs41_server_scope *cl_serverscope; | 92 | struct nfs41_server_scope *cl_serverscope; |
89 | struct nfs41_impl_id *cl_implid; | 93 | struct nfs41_impl_id *cl_implid; |
94 | /* nfs 4.1+ state protection modes: */ | ||
95 | unsigned long cl_sp4_flags; | ||
96 | #define NFS_SP4_MACH_CRED_MINIMAL 1 /* Minimal sp4_mach_cred - state ops | ||
97 | * must use machine cred */ | ||
98 | #define NFS_SP4_MACH_CRED_CLEANUP 2 /* CLOSE and LOCKU */ | ||
99 | #define NFS_SP4_MACH_CRED_SECINFO 3 /* SECINFO and SECINFO_NO_NAME */ | ||
100 | #define NFS_SP4_MACH_CRED_STATEID 4 /* TEST_STATEID and FREE_STATEID */ | ||
101 | #define NFS_SP4_MACH_CRED_WRITE 5 /* WRITE */ | ||
102 | #define NFS_SP4_MACH_CRED_COMMIT 6 /* COMMIT */ | ||
90 | #endif /* CONFIG_NFS_V4 */ | 103 | #endif /* CONFIG_NFS_V4 */ |
91 | 104 | ||
92 | #ifdef CONFIG_NFS_FSCACHE | 105 | #ifdef CONFIG_NFS_FSCACHE |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 8651574a305b..01fd84b566f7 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1107,6 +1107,23 @@ struct pnfs_ds_commit_info { | |||
1107 | struct pnfs_commit_bucket *buckets; | 1107 | struct pnfs_commit_bucket *buckets; |
1108 | }; | 1108 | }; |
1109 | 1109 | ||
1110 | #define NFS4_OP_MAP_NUM_LONGS \ | ||
1111 | DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long)) | ||
1112 | #define NFS4_OP_MAP_NUM_WORDS \ | ||
1113 | (NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32)) | ||
1114 | struct nfs4_op_map { | ||
1115 | union { | ||
1116 | unsigned long longs[NFS4_OP_MAP_NUM_LONGS]; | ||
1117 | u32 words[NFS4_OP_MAP_NUM_WORDS]; | ||
1118 | } u; | ||
1119 | }; | ||
1120 | |||
1121 | struct nfs41_state_protection { | ||
1122 | u32 how; | ||
1123 | struct nfs4_op_map enforce; | ||
1124 | struct nfs4_op_map allow; | ||
1125 | }; | ||
1126 | |||
1110 | #define NFS4_EXCHANGE_ID_LEN (48) | 1127 | #define NFS4_EXCHANGE_ID_LEN (48) |
1111 | struct nfs41_exchange_id_args { | 1128 | struct nfs41_exchange_id_args { |
1112 | struct nfs_client *client; | 1129 | struct nfs_client *client; |
@@ -1114,6 +1131,7 @@ struct nfs41_exchange_id_args { | |||
1114 | unsigned int id_len; | 1131 | unsigned int id_len; |
1115 | char id[NFS4_EXCHANGE_ID_LEN]; | 1132 | char id[NFS4_EXCHANGE_ID_LEN]; |
1116 | u32 flags; | 1133 | u32 flags; |
1134 | struct nfs41_state_protection state_protect; | ||
1117 | }; | 1135 | }; |
1118 | 1136 | ||
1119 | struct nfs41_server_owner { | 1137 | struct nfs41_server_owner { |
@@ -1146,6 +1164,7 @@ struct nfs41_exchange_id_res { | |||
1146 | struct nfs41_server_owner *server_owner; | 1164 | struct nfs41_server_owner *server_owner; |
1147 | struct nfs41_server_scope *server_scope; | 1165 | struct nfs41_server_scope *server_scope; |
1148 | struct nfs41_impl_id *impl_id; | 1166 | struct nfs41_impl_id *impl_id; |
1167 | struct nfs41_state_protection state_protect; | ||
1149 | }; | 1168 | }; |
1150 | 1169 | ||
1151 | struct nfs41_create_session_args { | 1170 | struct nfs41_create_session_args { |
@@ -1419,12 +1438,12 @@ struct nfs_rpc_ops { | |||
1419 | void (*read_setup) (struct nfs_read_data *, struct rpc_message *); | 1438 | void (*read_setup) (struct nfs_read_data *, struct rpc_message *); |
1420 | void (*read_pageio_init)(struct nfs_pageio_descriptor *, struct inode *, | 1439 | void (*read_pageio_init)(struct nfs_pageio_descriptor *, struct inode *, |
1421 | const struct nfs_pgio_completion_ops *); | 1440 | const struct nfs_pgio_completion_ops *); |
1422 | void (*read_rpc_prepare)(struct rpc_task *, struct nfs_read_data *); | 1441 | int (*read_rpc_prepare)(struct rpc_task *, struct nfs_read_data *); |
1423 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); | 1442 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); |
1424 | void (*write_setup) (struct nfs_write_data *, struct rpc_message *); | 1443 | void (*write_setup) (struct nfs_write_data *, struct rpc_message *); |
1425 | void (*write_pageio_init)(struct nfs_pageio_descriptor *, struct inode *, int, | 1444 | void (*write_pageio_init)(struct nfs_pageio_descriptor *, struct inode *, int, |
1426 | const struct nfs_pgio_completion_ops *); | 1445 | const struct nfs_pgio_completion_ops *); |
1427 | void (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *); | 1446 | int (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *); |
1428 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); | 1447 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); |
1429 | void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *); | 1448 | void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *); |
1430 | void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *); | 1449 | void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *); |
@@ -1442,7 +1461,7 @@ struct nfs_rpc_ops { | |||
1442 | struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *); | 1461 | struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *); |
1443 | struct nfs_client * | 1462 | struct nfs_client * |
1444 | (*init_client) (struct nfs_client *, const struct rpc_timeout *, | 1463 | (*init_client) (struct nfs_client *, const struct rpc_timeout *, |
1445 | const char *, rpc_authflavor_t); | 1464 | const char *); |
1446 | void (*free_client) (struct nfs_client *); | 1465 | void (*free_client) (struct nfs_client *); |
1447 | struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *); | 1466 | struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *); |
1448 | struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *, | 1467 | struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *, |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 0dd00f4f6810..790be1472792 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -24,12 +24,21 @@ | |||
24 | 24 | ||
25 | struct rpcsec_gss_info; | 25 | struct rpcsec_gss_info; |
26 | 26 | ||
27 | /* auth_cred ac_flags bits */ | ||
28 | enum { | ||
29 | RPC_CRED_NO_CRKEY_TIMEOUT = 0, /* underlying cred has no key timeout */ | ||
30 | RPC_CRED_KEY_EXPIRE_SOON = 1, /* underlying cred key will expire soon */ | ||
31 | RPC_CRED_NOTIFY_TIMEOUT = 2, /* nofity generic cred when underlying | ||
32 | key will expire soon */ | ||
33 | }; | ||
34 | |||
27 | /* Work around the lack of a VFS credential */ | 35 | /* Work around the lack of a VFS credential */ |
28 | struct auth_cred { | 36 | struct auth_cred { |
29 | kuid_t uid; | 37 | kuid_t uid; |
30 | kgid_t gid; | 38 | kgid_t gid; |
31 | struct group_info *group_info; | 39 | struct group_info *group_info; |
32 | const char *principal; | 40 | const char *principal; |
41 | unsigned long ac_flags; | ||
33 | unsigned char machine_cred : 1; | 42 | unsigned char machine_cred : 1; |
34 | }; | 43 | }; |
35 | 44 | ||
@@ -87,6 +96,11 @@ struct rpc_auth { | |||
87 | /* per-flavor data */ | 96 | /* per-flavor data */ |
88 | }; | 97 | }; |
89 | 98 | ||
99 | struct rpc_auth_create_args { | ||
100 | rpc_authflavor_t pseudoflavor; | ||
101 | const char *target_name; | ||
102 | }; | ||
103 | |||
90 | /* Flags for rpcauth_lookupcred() */ | 104 | /* Flags for rpcauth_lookupcred() */ |
91 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ | 105 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ |
92 | 106 | ||
@@ -97,17 +111,17 @@ struct rpc_authops { | |||
97 | struct module *owner; | 111 | struct module *owner; |
98 | rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */ | 112 | rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */ |
99 | char * au_name; | 113 | char * au_name; |
100 | struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t); | 114 | struct rpc_auth * (*create)(struct rpc_auth_create_args *, struct rpc_clnt *); |
101 | void (*destroy)(struct rpc_auth *); | 115 | void (*destroy)(struct rpc_auth *); |
102 | 116 | ||
103 | struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); | 117 | struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); |
104 | struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); | 118 | struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); |
105 | int (*pipes_create)(struct rpc_auth *); | ||
106 | void (*pipes_destroy)(struct rpc_auth *); | ||
107 | int (*list_pseudoflavors)(rpc_authflavor_t *, int); | 119 | int (*list_pseudoflavors)(rpc_authflavor_t *, int); |
108 | rpc_authflavor_t (*info2flavor)(struct rpcsec_gss_info *); | 120 | rpc_authflavor_t (*info2flavor)(struct rpcsec_gss_info *); |
109 | int (*flavor2info)(rpc_authflavor_t, | 121 | int (*flavor2info)(rpc_authflavor_t, |
110 | struct rpcsec_gss_info *); | 122 | struct rpcsec_gss_info *); |
123 | int (*key_timeout)(struct rpc_auth *, | ||
124 | struct rpc_cred *); | ||
111 | }; | 125 | }; |
112 | 126 | ||
113 | struct rpc_credops { | 127 | struct rpc_credops { |
@@ -124,6 +138,8 @@ struct rpc_credops { | |||
124 | void *, __be32 *, void *); | 138 | void *, __be32 *, void *); |
125 | int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t, | 139 | int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t, |
126 | void *, __be32 *, void *); | 140 | void *, __be32 *, void *); |
141 | int (*crkey_timeout)(struct rpc_cred *); | ||
142 | bool (*crkey_to_expire)(struct rpc_cred *); | ||
127 | }; | 143 | }; |
128 | 144 | ||
129 | extern const struct rpc_authops authunix_ops; | 145 | extern const struct rpc_authops authunix_ops; |
@@ -140,7 +156,8 @@ struct rpc_cred * rpc_lookup_cred(void); | |||
140 | struct rpc_cred * rpc_lookup_machine_cred(const char *service_name); | 156 | struct rpc_cred * rpc_lookup_machine_cred(const char *service_name); |
141 | int rpcauth_register(const struct rpc_authops *); | 157 | int rpcauth_register(const struct rpc_authops *); |
142 | int rpcauth_unregister(const struct rpc_authops *); | 158 | int rpcauth_unregister(const struct rpc_authops *); |
143 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); | 159 | struct rpc_auth * rpcauth_create(struct rpc_auth_create_args *, |
160 | struct rpc_clnt *); | ||
144 | void rpcauth_release(struct rpc_auth *); | 161 | void rpcauth_release(struct rpc_auth *); |
145 | rpc_authflavor_t rpcauth_get_pseudoflavor(rpc_authflavor_t, | 162 | rpc_authflavor_t rpcauth_get_pseudoflavor(rpc_authflavor_t, |
146 | struct rpcsec_gss_info *); | 163 | struct rpcsec_gss_info *); |
@@ -162,6 +179,9 @@ int rpcauth_uptodatecred(struct rpc_task *); | |||
162 | int rpcauth_init_credcache(struct rpc_auth *); | 179 | int rpcauth_init_credcache(struct rpc_auth *); |
163 | void rpcauth_destroy_credcache(struct rpc_auth *); | 180 | void rpcauth_destroy_credcache(struct rpc_auth *); |
164 | void rpcauth_clear_credcache(struct rpc_cred_cache *); | 181 | void rpcauth_clear_credcache(struct rpc_cred_cache *); |
182 | int rpcauth_key_timeout_notify(struct rpc_auth *, | ||
183 | struct rpc_cred *); | ||
184 | bool rpcauth_cred_key_to_expire(struct rpc_cred *); | ||
165 | 185 | ||
166 | static inline | 186 | static inline |
167 | struct rpc_cred * get_rpccred(struct rpc_cred *cred) | 187 | struct rpc_cred * get_rpccred(struct rpc_cred *cred) |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index bfe11be81f6f..6740801aa71a 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/sunrpc/stats.h> | 21 | #include <linux/sunrpc/stats.h> |
22 | #include <linux/sunrpc/xdr.h> | 22 | #include <linux/sunrpc/xdr.h> |
23 | #include <linux/sunrpc/timer.h> | 23 | #include <linux/sunrpc/timer.h> |
24 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
24 | #include <asm/signal.h> | 25 | #include <asm/signal.h> |
25 | #include <linux/path.h> | 26 | #include <linux/path.h> |
26 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
@@ -32,6 +33,7 @@ struct rpc_inode; | |||
32 | */ | 33 | */ |
33 | struct rpc_clnt { | 34 | struct rpc_clnt { |
34 | atomic_t cl_count; /* Number of references */ | 35 | atomic_t cl_count; /* Number of references */ |
36 | unsigned int cl_clid; /* client id */ | ||
35 | struct list_head cl_clients; /* Global list of clients */ | 37 | struct list_head cl_clients; /* Global list of clients */ |
36 | struct list_head cl_tasks; /* List of tasks */ | 38 | struct list_head cl_tasks; /* List of tasks */ |
37 | spinlock_t cl_lock; /* spinlock */ | 39 | spinlock_t cl_lock; /* spinlock */ |
@@ -41,7 +43,6 @@ struct rpc_clnt { | |||
41 | cl_vers, /* RPC version number */ | 43 | cl_vers, /* RPC version number */ |
42 | cl_maxproc; /* max procedure number */ | 44 | cl_maxproc; /* max procedure number */ |
43 | 45 | ||
44 | const char * cl_protname; /* protocol name */ | ||
45 | struct rpc_auth * cl_auth; /* authenticator */ | 46 | struct rpc_auth * cl_auth; /* authenticator */ |
46 | struct rpc_stat * cl_stats; /* per-program statistics */ | 47 | struct rpc_stat * cl_stats; /* per-program statistics */ |
47 | struct rpc_iostats * cl_metrics; /* per-client statistics */ | 48 | struct rpc_iostats * cl_metrics; /* per-client statistics */ |
@@ -56,12 +57,11 @@ struct rpc_clnt { | |||
56 | 57 | ||
57 | int cl_nodelen; /* nodename length */ | 58 | int cl_nodelen; /* nodename length */ |
58 | char cl_nodename[UNX_MAXNODENAME]; | 59 | char cl_nodename[UNX_MAXNODENAME]; |
59 | struct dentry * cl_dentry; | 60 | struct rpc_pipe_dir_head cl_pipedir_objects; |
60 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ | 61 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ |
61 | struct rpc_rtt cl_rtt_default; | 62 | struct rpc_rtt cl_rtt_default; |
62 | struct rpc_timeout cl_timeout_default; | 63 | struct rpc_timeout cl_timeout_default; |
63 | const struct rpc_program *cl_program; | 64 | const struct rpc_program *cl_program; |
64 | char *cl_principal; /* target to authenticate to */ | ||
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* | 67 | /* |
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index aa5b582cc471..a353e0300b54 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h | |||
@@ -5,6 +5,26 @@ | |||
5 | 5 | ||
6 | #include <linux/workqueue.h> | 6 | #include <linux/workqueue.h> |
7 | 7 | ||
8 | struct rpc_pipe_dir_head { | ||
9 | struct list_head pdh_entries; | ||
10 | struct dentry *pdh_dentry; | ||
11 | }; | ||
12 | |||
13 | struct rpc_pipe_dir_object_ops; | ||
14 | struct rpc_pipe_dir_object { | ||
15 | struct list_head pdo_head; | ||
16 | const struct rpc_pipe_dir_object_ops *pdo_ops; | ||
17 | |||
18 | void *pdo_data; | ||
19 | }; | ||
20 | |||
21 | struct rpc_pipe_dir_object_ops { | ||
22 | int (*create)(struct dentry *dir, | ||
23 | struct rpc_pipe_dir_object *pdo); | ||
24 | void (*destroy)(struct dentry *dir, | ||
25 | struct rpc_pipe_dir_object *pdo); | ||
26 | }; | ||
27 | |||
8 | struct rpc_pipe_msg { | 28 | struct rpc_pipe_msg { |
9 | struct list_head list; | 29 | struct list_head list; |
10 | void *data; | 30 | void *data; |
@@ -74,7 +94,24 @@ extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *); | |||
74 | 94 | ||
75 | struct rpc_clnt; | 95 | struct rpc_clnt; |
76 | extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); | 96 | extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); |
77 | extern int rpc_remove_client_dir(struct dentry *); | 97 | extern int rpc_remove_client_dir(struct rpc_clnt *); |
98 | |||
99 | extern void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh); | ||
100 | extern void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo, | ||
101 | const struct rpc_pipe_dir_object_ops *pdo_ops, | ||
102 | void *pdo_data); | ||
103 | extern int rpc_add_pipe_dir_object(struct net *net, | ||
104 | struct rpc_pipe_dir_head *pdh, | ||
105 | struct rpc_pipe_dir_object *pdo); | ||
106 | extern void rpc_remove_pipe_dir_object(struct net *net, | ||
107 | struct rpc_pipe_dir_head *pdh, | ||
108 | struct rpc_pipe_dir_object *pdo); | ||
109 | extern struct rpc_pipe_dir_object *rpc_find_or_alloc_pipe_dir_object( | ||
110 | struct net *net, | ||
111 | struct rpc_pipe_dir_head *pdh, | ||
112 | int (*match)(struct rpc_pipe_dir_object *, void *), | ||
113 | struct rpc_pipe_dir_object *(*alloc)(void *), | ||
114 | void *data); | ||
78 | 115 | ||
79 | struct cache_detail; | 116 | struct cache_detail; |
80 | extern struct dentry *rpc_create_cache_dir(struct dentry *, | 117 | extern struct dentry *rpc_create_cache_dir(struct dentry *, |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 1821445708d6..096ee58be11a 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -79,7 +79,7 @@ struct rpc_task { | |||
79 | unsigned short tk_flags; /* misc flags */ | 79 | unsigned short tk_flags; /* misc flags */ |
80 | unsigned short tk_timeouts; /* maj timeouts */ | 80 | unsigned short tk_timeouts; /* maj timeouts */ |
81 | 81 | ||
82 | #ifdef RPC_DEBUG | 82 | #if defined(RPC_DEBUG) || defined(RPC_TRACEPOINTS) |
83 | unsigned short tk_pid; /* debugging aid */ | 83 | unsigned short tk_pid; /* debugging aid */ |
84 | #endif | 84 | #endif |
85 | unsigned char tk_priority : 2,/* Task priority */ | 85 | unsigned char tk_priority : 2,/* Task priority */ |
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 43be87d5dd58..d51d16c7afd8 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | #include <linux/sunrpc/sched.h> | 7 | #include <linux/sunrpc/sched.h> |
8 | #include <linux/sunrpc/clnt.h> | 8 | #include <linux/sunrpc/clnt.h> |
9 | #include <net/tcp_states.h> | ||
10 | #include <linux/net.h> | ||
9 | #include <linux/tracepoint.h> | 11 | #include <linux/tracepoint.h> |
10 | 12 | ||
11 | DECLARE_EVENT_CLASS(rpc_task_status, | 13 | DECLARE_EVENT_CLASS(rpc_task_status, |
@@ -15,18 +17,20 @@ DECLARE_EVENT_CLASS(rpc_task_status, | |||
15 | TP_ARGS(task), | 17 | TP_ARGS(task), |
16 | 18 | ||
17 | TP_STRUCT__entry( | 19 | TP_STRUCT__entry( |
18 | __field(const struct rpc_task *, task) | 20 | __field(unsigned int, task_id) |
19 | __field(const struct rpc_clnt *, clnt) | 21 | __field(unsigned int, client_id) |
20 | __field(int, status) | 22 | __field(int, status) |
21 | ), | 23 | ), |
22 | 24 | ||
23 | TP_fast_assign( | 25 | TP_fast_assign( |
24 | __entry->task = task; | 26 | __entry->task_id = task->tk_pid; |
25 | __entry->clnt = task->tk_client; | 27 | __entry->client_id = task->tk_client->cl_clid; |
26 | __entry->status = task->tk_status; | 28 | __entry->status = task->tk_status; |
27 | ), | 29 | ), |
28 | 30 | ||
29 | TP_printk("task:%p@%p, status %d",__entry->task, __entry->clnt, __entry->status) | 31 | TP_printk("task:%u@%u, status %d", |
32 | __entry->task_id, __entry->client_id, | ||
33 | __entry->status) | ||
30 | ); | 34 | ); |
31 | 35 | ||
32 | DEFINE_EVENT(rpc_task_status, rpc_call_status, | 36 | DEFINE_EVENT(rpc_task_status, rpc_call_status, |
@@ -47,18 +51,20 @@ TRACE_EVENT(rpc_connect_status, | |||
47 | TP_ARGS(task, status), | 51 | TP_ARGS(task, status), |
48 | 52 | ||
49 | TP_STRUCT__entry( | 53 | TP_STRUCT__entry( |
50 | __field(const struct rpc_task *, task) | 54 | __field(unsigned int, task_id) |
51 | __field(const struct rpc_clnt *, clnt) | 55 | __field(unsigned int, client_id) |
52 | __field(int, status) | 56 | __field(int, status) |
53 | ), | 57 | ), |
54 | 58 | ||
55 | TP_fast_assign( | 59 | TP_fast_assign( |
56 | __entry->task = task; | 60 | __entry->task_id = task->tk_pid; |
57 | __entry->clnt = task->tk_client; | 61 | __entry->client_id = task->tk_client->cl_clid; |
58 | __entry->status = status; | 62 | __entry->status = status; |
59 | ), | 63 | ), |
60 | 64 | ||
61 | TP_printk("task:%p@%p, status %d",__entry->task, __entry->clnt, __entry->status) | 65 | TP_printk("task:%u@%u, status %d", |
66 | __entry->task_id, __entry->client_id, | ||
67 | __entry->status) | ||
62 | ); | 68 | ); |
63 | 69 | ||
64 | DECLARE_EVENT_CLASS(rpc_task_running, | 70 | DECLARE_EVENT_CLASS(rpc_task_running, |
@@ -68,8 +74,8 @@ DECLARE_EVENT_CLASS(rpc_task_running, | |||
68 | TP_ARGS(clnt, task, action), | 74 | TP_ARGS(clnt, task, action), |
69 | 75 | ||
70 | TP_STRUCT__entry( | 76 | TP_STRUCT__entry( |
71 | __field(const struct rpc_clnt *, clnt) | 77 | __field(unsigned int, task_id) |
72 | __field(const struct rpc_task *, task) | 78 | __field(unsigned int, client_id) |
73 | __field(const void *, action) | 79 | __field(const void *, action) |
74 | __field(unsigned long, runstate) | 80 | __field(unsigned long, runstate) |
75 | __field(int, status) | 81 | __field(int, status) |
@@ -77,17 +83,16 @@ DECLARE_EVENT_CLASS(rpc_task_running, | |||
77 | ), | 83 | ), |
78 | 84 | ||
79 | TP_fast_assign( | 85 | TP_fast_assign( |
80 | __entry->clnt = clnt; | 86 | __entry->client_id = clnt->cl_clid; |
81 | __entry->task = task; | 87 | __entry->task_id = task->tk_pid; |
82 | __entry->action = action; | 88 | __entry->action = action; |
83 | __entry->runstate = task->tk_runstate; | 89 | __entry->runstate = task->tk_runstate; |
84 | __entry->status = task->tk_status; | 90 | __entry->status = task->tk_status; |
85 | __entry->flags = task->tk_flags; | 91 | __entry->flags = task->tk_flags; |
86 | ), | 92 | ), |
87 | 93 | ||
88 | TP_printk("task:%p@%p flags=%4.4x state=%4.4lx status=%d action=%pf", | 94 | TP_printk("task:%u@%u flags=%4.4x state=%4.4lx status=%d action=%pf", |
89 | __entry->task, | 95 | __entry->task_id, __entry->client_id, |
90 | __entry->clnt, | ||
91 | __entry->flags, | 96 | __entry->flags, |
92 | __entry->runstate, | 97 | __entry->runstate, |
93 | __entry->status, | 98 | __entry->status, |
@@ -126,8 +131,8 @@ DECLARE_EVENT_CLASS(rpc_task_queued, | |||
126 | TP_ARGS(clnt, task, q), | 131 | TP_ARGS(clnt, task, q), |
127 | 132 | ||
128 | TP_STRUCT__entry( | 133 | TP_STRUCT__entry( |
129 | __field(const struct rpc_clnt *, clnt) | 134 | __field(unsigned int, task_id) |
130 | __field(const struct rpc_task *, task) | 135 | __field(unsigned int, client_id) |
131 | __field(unsigned long, timeout) | 136 | __field(unsigned long, timeout) |
132 | __field(unsigned long, runstate) | 137 | __field(unsigned long, runstate) |
133 | __field(int, status) | 138 | __field(int, status) |
@@ -136,8 +141,8 @@ DECLARE_EVENT_CLASS(rpc_task_queued, | |||
136 | ), | 141 | ), |
137 | 142 | ||
138 | TP_fast_assign( | 143 | TP_fast_assign( |
139 | __entry->clnt = clnt; | 144 | __entry->client_id = clnt->cl_clid; |
140 | __entry->task = task; | 145 | __entry->task_id = task->tk_pid; |
141 | __entry->timeout = task->tk_timeout; | 146 | __entry->timeout = task->tk_timeout; |
142 | __entry->runstate = task->tk_runstate; | 147 | __entry->runstate = task->tk_runstate; |
143 | __entry->status = task->tk_status; | 148 | __entry->status = task->tk_status; |
@@ -145,9 +150,8 @@ DECLARE_EVENT_CLASS(rpc_task_queued, | |||
145 | __assign_str(q_name, rpc_qname(q)); | 150 | __assign_str(q_name, rpc_qname(q)); |
146 | ), | 151 | ), |
147 | 152 | ||
148 | TP_printk("task:%p@%p flags=%4.4x state=%4.4lx status=%d timeout=%lu queue=%s", | 153 | TP_printk("task:%u@%u flags=%4.4x state=%4.4lx status=%d timeout=%lu queue=%s", |
149 | __entry->task, | 154 | __entry->task_id, __entry->client_id, |
150 | __entry->clnt, | ||
151 | __entry->flags, | 155 | __entry->flags, |
152 | __entry->runstate, | 156 | __entry->runstate, |
153 | __entry->status, | 157 | __entry->status, |
@@ -172,6 +176,135 @@ DEFINE_EVENT(rpc_task_queued, rpc_task_wakeup, | |||
172 | 176 | ||
173 | ); | 177 | ); |
174 | 178 | ||
179 | #define rpc_show_socket_state(state) \ | ||
180 | __print_symbolic(state, \ | ||
181 | { SS_FREE, "FREE" }, \ | ||
182 | { SS_UNCONNECTED, "UNCONNECTED" }, \ | ||
183 | { SS_CONNECTING, "CONNECTING," }, \ | ||
184 | { SS_CONNECTED, "CONNECTED," }, \ | ||
185 | { SS_DISCONNECTING, "DISCONNECTING" }) | ||
186 | |||
187 | #define rpc_show_sock_state(state) \ | ||
188 | __print_symbolic(state, \ | ||
189 | { TCP_ESTABLISHED, "ESTABLISHED" }, \ | ||
190 | { TCP_SYN_SENT, "SYN_SENT" }, \ | ||
191 | { TCP_SYN_RECV, "SYN_RECV" }, \ | ||
192 | { TCP_FIN_WAIT1, "FIN_WAIT1" }, \ | ||
193 | { TCP_FIN_WAIT2, "FIN_WAIT2" }, \ | ||
194 | { TCP_TIME_WAIT, "TIME_WAIT" }, \ | ||
195 | { TCP_CLOSE, "CLOSE" }, \ | ||
196 | { TCP_CLOSE_WAIT, "CLOSE_WAIT" }, \ | ||
197 | { TCP_LAST_ACK, "LAST_ACK" }, \ | ||
198 | { TCP_LISTEN, "LISTEN" }, \ | ||
199 | { TCP_CLOSING, "CLOSING" }) | ||
200 | |||
201 | DECLARE_EVENT_CLASS(xs_socket_event, | ||
202 | |||
203 | TP_PROTO( | ||
204 | struct rpc_xprt *xprt, | ||
205 | struct socket *socket | ||
206 | ), | ||
207 | |||
208 | TP_ARGS(xprt, socket), | ||
209 | |||
210 | TP_STRUCT__entry( | ||
211 | __field(unsigned int, socket_state) | ||
212 | __field(unsigned int, sock_state) | ||
213 | __field(unsigned long long, ino) | ||
214 | __string(dstaddr, | ||
215 | xprt->address_strings[RPC_DISPLAY_ADDR]) | ||
216 | __string(dstport, | ||
217 | xprt->address_strings[RPC_DISPLAY_PORT]) | ||
218 | ), | ||
219 | |||
220 | TP_fast_assign( | ||
221 | struct inode *inode = SOCK_INODE(socket); | ||
222 | __entry->socket_state = socket->state; | ||
223 | __entry->sock_state = socket->sk->sk_state; | ||
224 | __entry->ino = (unsigned long long)inode->i_ino; | ||
225 | __assign_str(dstaddr, | ||
226 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
227 | __assign_str(dstport, | ||
228 | xprt->address_strings[RPC_DISPLAY_PORT]); | ||
229 | ), | ||
230 | |||
231 | TP_printk( | ||
232 | "socket:[%llu] dstaddr=%s/%s " | ||
233 | "state=%u (%s) sk_state=%u (%s)", | ||
234 | __entry->ino, __get_str(dstaddr), __get_str(dstport), | ||
235 | __entry->socket_state, | ||
236 | rpc_show_socket_state(__entry->socket_state), | ||
237 | __entry->sock_state, | ||
238 | rpc_show_sock_state(__entry->sock_state) | ||
239 | ) | ||
240 | ); | ||
241 | #define DEFINE_RPC_SOCKET_EVENT(name) \ | ||
242 | DEFINE_EVENT(xs_socket_event, name, \ | ||
243 | TP_PROTO( \ | ||
244 | struct rpc_xprt *xprt, \ | ||
245 | struct socket *socket \ | ||
246 | ), \ | ||
247 | TP_ARGS(xprt, socket)) | ||
248 | |||
249 | DECLARE_EVENT_CLASS(xs_socket_event_done, | ||
250 | |||
251 | TP_PROTO( | ||
252 | struct rpc_xprt *xprt, | ||
253 | struct socket *socket, | ||
254 | int error | ||
255 | ), | ||
256 | |||
257 | TP_ARGS(xprt, socket, error), | ||
258 | |||
259 | TP_STRUCT__entry( | ||
260 | __field(int, error) | ||
261 | __field(unsigned int, socket_state) | ||
262 | __field(unsigned int, sock_state) | ||
263 | __field(unsigned long long, ino) | ||
264 | __string(dstaddr, | ||
265 | xprt->address_strings[RPC_DISPLAY_ADDR]) | ||
266 | __string(dstport, | ||
267 | xprt->address_strings[RPC_DISPLAY_PORT]) | ||
268 | ), | ||
269 | |||
270 | TP_fast_assign( | ||
271 | struct inode *inode = SOCK_INODE(socket); | ||
272 | __entry->socket_state = socket->state; | ||
273 | __entry->sock_state = socket->sk->sk_state; | ||
274 | __entry->ino = (unsigned long long)inode->i_ino; | ||
275 | __entry->error = error; | ||
276 | __assign_str(dstaddr, | ||
277 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
278 | __assign_str(dstport, | ||
279 | xprt->address_strings[RPC_DISPLAY_PORT]); | ||
280 | ), | ||
281 | |||
282 | TP_printk( | ||
283 | "error=%d socket:[%llu] dstaddr=%s/%s " | ||
284 | "state=%u (%s) sk_state=%u (%s)", | ||
285 | __entry->error, | ||
286 | __entry->ino, __get_str(dstaddr), __get_str(dstport), | ||
287 | __entry->socket_state, | ||
288 | rpc_show_socket_state(__entry->socket_state), | ||
289 | __entry->sock_state, | ||
290 | rpc_show_sock_state(__entry->sock_state) | ||
291 | ) | ||
292 | ); | ||
293 | #define DEFINE_RPC_SOCKET_EVENT_DONE(name) \ | ||
294 | DEFINE_EVENT(xs_socket_event_done, name, \ | ||
295 | TP_PROTO( \ | ||
296 | struct rpc_xprt *xprt, \ | ||
297 | struct socket *socket, \ | ||
298 | int error \ | ||
299 | ), \ | ||
300 | TP_ARGS(xprt, socket, error)) | ||
301 | |||
302 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_state_change); | ||
303 | DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_connect); | ||
304 | DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_reset_connection); | ||
305 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_close); | ||
306 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_shutdown); | ||
307 | |||
175 | #endif /* _TRACE_SUNRPC_H */ | 308 | #endif /* _TRACE_SUNRPC_H */ |
176 | 309 | ||
177 | #include <trace/define_trace.h> | 310 | #include <trace/define_trace.h> |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index ed2fdd210c0b..415159061cd0 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -250,11 +250,11 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size) | |||
250 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | 250 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); |
251 | 251 | ||
252 | struct rpc_auth * | 252 | struct rpc_auth * |
253 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 253 | rpcauth_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
254 | { | 254 | { |
255 | struct rpc_auth *auth; | 255 | struct rpc_auth *auth; |
256 | const struct rpc_authops *ops; | 256 | const struct rpc_authops *ops; |
257 | u32 flavor = pseudoflavor_to_flavor(pseudoflavor); | 257 | u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor); |
258 | 258 | ||
259 | auth = ERR_PTR(-EINVAL); | 259 | auth = ERR_PTR(-EINVAL); |
260 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 260 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -269,7 +269,7 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | |||
269 | goto out; | 269 | goto out; |
270 | } | 270 | } |
271 | spin_unlock(&rpc_authflavor_lock); | 271 | spin_unlock(&rpc_authflavor_lock); |
272 | auth = ops->create(clnt, pseudoflavor); | 272 | auth = ops->create(args, clnt); |
273 | module_put(ops->owner); | 273 | module_put(ops->owner); |
274 | if (IS_ERR(auth)) | 274 | if (IS_ERR(auth)) |
275 | return auth; | 275 | return auth; |
@@ -343,6 +343,27 @@ out_nocache: | |||
343 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | 343 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); |
344 | 344 | ||
345 | /* | 345 | /* |
346 | * Setup a credential key lifetime timeout notification | ||
347 | */ | ||
348 | int | ||
349 | rpcauth_key_timeout_notify(struct rpc_auth *auth, struct rpc_cred *cred) | ||
350 | { | ||
351 | if (!cred->cr_auth->au_ops->key_timeout) | ||
352 | return 0; | ||
353 | return cred->cr_auth->au_ops->key_timeout(auth, cred); | ||
354 | } | ||
355 | EXPORT_SYMBOL_GPL(rpcauth_key_timeout_notify); | ||
356 | |||
357 | bool | ||
358 | rpcauth_cred_key_to_expire(struct rpc_cred *cred) | ||
359 | { | ||
360 | if (!cred->cr_ops->crkey_to_expire) | ||
361 | return false; | ||
362 | return cred->cr_ops->crkey_to_expire(cred); | ||
363 | } | ||
364 | EXPORT_SYMBOL_GPL(rpcauth_cred_key_to_expire); | ||
365 | |||
366 | /* | ||
346 | * Destroy a list of credentials | 367 | * Destroy a list of credentials |
347 | */ | 368 | */ |
348 | static inline | 369 | static inline |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index b6badafc6494..f6d84be49050 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -89,6 +89,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
89 | gcred->acred.uid = acred->uid; | 89 | gcred->acred.uid = acred->uid; |
90 | gcred->acred.gid = acred->gid; | 90 | gcred->acred.gid = acred->gid; |
91 | gcred->acred.group_info = acred->group_info; | 91 | gcred->acred.group_info = acred->group_info; |
92 | gcred->acred.ac_flags = 0; | ||
92 | if (gcred->acred.group_info != NULL) | 93 | if (gcred->acred.group_info != NULL) |
93 | get_group_info(gcred->acred.group_info); | 94 | get_group_info(gcred->acred.group_info); |
94 | gcred->acred.machine_cred = acred->machine_cred; | 95 | gcred->acred.machine_cred = acred->machine_cred; |
@@ -182,11 +183,78 @@ void rpc_destroy_generic_auth(void) | |||
182 | rpcauth_destroy_credcache(&generic_auth); | 183 | rpcauth_destroy_credcache(&generic_auth); |
183 | } | 184 | } |
184 | 185 | ||
186 | /* | ||
187 | * Test the the current time (now) against the underlying credential key expiry | ||
188 | * minus a timeout and setup notification. | ||
189 | * | ||
190 | * The normal case: | ||
191 | * If 'now' is before the key expiry minus RPC_KEY_EXPIRE_TIMEO, set | ||
192 | * the RPC_CRED_NOTIFY_TIMEOUT flag to setup the underlying credential | ||
193 | * rpc_credops crmatch routine to notify this generic cred when it's key | ||
194 | * expiration is within RPC_KEY_EXPIRE_TIMEO, and return 0. | ||
195 | * | ||
196 | * The error case: | ||
197 | * If the underlying cred lookup fails, return -EACCES. | ||
198 | * | ||
199 | * The 'almost' error case: | ||
200 | * If 'now' is within key expiry minus RPC_KEY_EXPIRE_TIMEO, but not within | ||
201 | * key expiry minus RPC_KEY_EXPIRE_FAIL, set the RPC_CRED_EXPIRE_SOON bit | ||
202 | * on the acred ac_flags and return 0. | ||
203 | */ | ||
204 | static int | ||
205 | generic_key_timeout(struct rpc_auth *auth, struct rpc_cred *cred) | ||
206 | { | ||
207 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
208 | gc_base)->acred; | ||
209 | struct rpc_cred *tcred; | ||
210 | int ret = 0; | ||
211 | |||
212 | |||
213 | /* Fast track for non crkey_timeout (no key) underlying credentials */ | ||
214 | if (test_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags)) | ||
215 | return 0; | ||
216 | |||
217 | /* Fast track for the normal case */ | ||
218 | if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags)) | ||
219 | return 0; | ||
220 | |||
221 | /* lookup_cred either returns a valid referenced rpc_cred, or PTR_ERR */ | ||
222 | tcred = auth->au_ops->lookup_cred(auth, acred, 0); | ||
223 | if (IS_ERR(tcred)) | ||
224 | return -EACCES; | ||
225 | |||
226 | if (!tcred->cr_ops->crkey_timeout) { | ||
227 | set_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags); | ||
228 | ret = 0; | ||
229 | goto out_put; | ||
230 | } | ||
231 | |||
232 | /* Test for the almost error case */ | ||
233 | ret = tcred->cr_ops->crkey_timeout(tcred); | ||
234 | if (ret != 0) { | ||
235 | set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
236 | ret = 0; | ||
237 | } else { | ||
238 | /* In case underlying cred key has been reset */ | ||
239 | if (test_and_clear_bit(RPC_CRED_KEY_EXPIRE_SOON, | ||
240 | &acred->ac_flags)) | ||
241 | dprintk("RPC: UID %d Credential key reset\n", | ||
242 | tcred->cr_uid); | ||
243 | /* set up fasttrack for the normal case */ | ||
244 | set_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); | ||
245 | } | ||
246 | |||
247 | out_put: | ||
248 | put_rpccred(tcred); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
185 | static const struct rpc_authops generic_auth_ops = { | 252 | static const struct rpc_authops generic_auth_ops = { |
186 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
187 | .au_name = "Generic", | 254 | .au_name = "Generic", |
188 | .lookup_cred = generic_lookup_cred, | 255 | .lookup_cred = generic_lookup_cred, |
189 | .crcreate = generic_create_cred, | 256 | .crcreate = generic_create_cred, |
257 | .key_timeout = generic_key_timeout, | ||
190 | }; | 258 | }; |
191 | 259 | ||
192 | static struct rpc_auth generic_auth = { | 260 | static struct rpc_auth generic_auth = { |
@@ -194,9 +262,23 @@ static struct rpc_auth generic_auth = { | |||
194 | .au_count = ATOMIC_INIT(0), | 262 | .au_count = ATOMIC_INIT(0), |
195 | }; | 263 | }; |
196 | 264 | ||
265 | static bool generic_key_to_expire(struct rpc_cred *cred) | ||
266 | { | ||
267 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
268 | gc_base)->acred; | ||
269 | bool ret; | ||
270 | |||
271 | get_rpccred(cred); | ||
272 | ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
273 | put_rpccred(cred); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
197 | static const struct rpc_credops generic_credops = { | 278 | static const struct rpc_credops generic_credops = { |
198 | .cr_name = "Generic cred", | 279 | .cr_name = "Generic cred", |
199 | .crdestroy = generic_destroy_cred, | 280 | .crdestroy = generic_destroy_cred, |
200 | .crbind = generic_bind_cred, | 281 | .crbind = generic_bind_cred, |
201 | .crmatch = generic_match, | 282 | .crmatch = generic_match, |
283 | .crkey_to_expire = generic_key_to_expire, | ||
202 | }; | 284 | }; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index fc2f78d6a9b4..30eb502135bb 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/sunrpc/rpc_pipe_fs.h> | 51 | #include <linux/sunrpc/rpc_pipe_fs.h> |
52 | #include <linux/sunrpc/gss_api.h> | 52 | #include <linux/sunrpc/gss_api.h> |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <linux/hashtable.h> | ||
54 | 55 | ||
55 | #include "../netns.h" | 56 | #include "../netns.h" |
56 | 57 | ||
@@ -62,6 +63,9 @@ static const struct rpc_credops gss_nullops; | |||
62 | #define GSS_RETRY_EXPIRED 5 | 63 | #define GSS_RETRY_EXPIRED 5 |
63 | static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; | 64 | static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; |
64 | 65 | ||
66 | #define GSS_KEY_EXPIRE_TIMEO 240 | ||
67 | static unsigned int gss_key_expire_timeo = GSS_KEY_EXPIRE_TIMEO; | ||
68 | |||
65 | #ifdef RPC_DEBUG | 69 | #ifdef RPC_DEBUG |
66 | # define RPCDBG_FACILITY RPCDBG_AUTH | 70 | # define RPCDBG_FACILITY RPCDBG_AUTH |
67 | #endif | 71 | #endif |
@@ -71,19 +75,33 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; | |||
71 | * using integrity (two 4-byte integers): */ | 75 | * using integrity (two 4-byte integers): */ |
72 | #define GSS_VERF_SLACK 100 | 76 | #define GSS_VERF_SLACK 100 |
73 | 77 | ||
78 | static DEFINE_HASHTABLE(gss_auth_hash_table, 16); | ||
79 | static DEFINE_SPINLOCK(gss_auth_hash_lock); | ||
80 | |||
81 | struct gss_pipe { | ||
82 | struct rpc_pipe_dir_object pdo; | ||
83 | struct rpc_pipe *pipe; | ||
84 | struct rpc_clnt *clnt; | ||
85 | const char *name; | ||
86 | struct kref kref; | ||
87 | }; | ||
88 | |||
74 | struct gss_auth { | 89 | struct gss_auth { |
75 | struct kref kref; | 90 | struct kref kref; |
91 | struct hlist_node hash; | ||
76 | struct rpc_auth rpc_auth; | 92 | struct rpc_auth rpc_auth; |
77 | struct gss_api_mech *mech; | 93 | struct gss_api_mech *mech; |
78 | enum rpc_gss_svc service; | 94 | enum rpc_gss_svc service; |
79 | struct rpc_clnt *client; | 95 | struct rpc_clnt *client; |
96 | struct net *net; | ||
80 | /* | 97 | /* |
81 | * There are two upcall pipes; dentry[1], named "gssd", is used | 98 | * There are two upcall pipes; dentry[1], named "gssd", is used |
82 | * for the new text-based upcall; dentry[0] is named after the | 99 | * for the new text-based upcall; dentry[0] is named after the |
83 | * mechanism (for example, "krb5") and exists for | 100 | * mechanism (for example, "krb5") and exists for |
84 | * backwards-compatibility with older gssd's. | 101 | * backwards-compatibility with older gssd's. |
85 | */ | 102 | */ |
86 | struct rpc_pipe *pipe[2]; | 103 | struct gss_pipe *gss_pipe[2]; |
104 | const char *target_name; | ||
87 | }; | 105 | }; |
88 | 106 | ||
89 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 107 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
@@ -294,7 +312,7 @@ static void put_pipe_version(struct net *net) | |||
294 | static void | 312 | static void |
295 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 313 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
296 | { | 314 | { |
297 | struct net *net = rpc_net_ns(gss_msg->auth->client); | 315 | struct net *net = gss_msg->auth->net; |
298 | if (!atomic_dec_and_test(&gss_msg->count)) | 316 | if (!atomic_dec_and_test(&gss_msg->count)) |
299 | return; | 317 | return; |
300 | put_pipe_version(net); | 318 | put_pipe_version(net); |
@@ -406,8 +424,8 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) | |||
406 | } | 424 | } |
407 | 425 | ||
408 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | 426 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, |
409 | struct rpc_clnt *clnt, | 427 | const char *service_name, |
410 | const char *service_name) | 428 | const char *target_name) |
411 | { | 429 | { |
412 | struct gss_api_mech *mech = gss_msg->auth->mech; | 430 | struct gss_api_mech *mech = gss_msg->auth->mech; |
413 | char *p = gss_msg->databuf; | 431 | char *p = gss_msg->databuf; |
@@ -417,8 +435,8 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
417 | mech->gm_name, | 435 | mech->gm_name, |
418 | from_kuid(&init_user_ns, gss_msg->uid)); | 436 | from_kuid(&init_user_ns, gss_msg->uid)); |
419 | p += gss_msg->msg.len; | 437 | p += gss_msg->msg.len; |
420 | if (clnt->cl_principal) { | 438 | if (target_name) { |
421 | len = sprintf(p, "target=%s ", clnt->cl_principal); | 439 | len = sprintf(p, "target=%s ", target_name); |
422 | p += len; | 440 | p += len; |
423 | gss_msg->msg.len += len; | 441 | gss_msg->msg.len += len; |
424 | } | 442 | } |
@@ -439,21 +457,8 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
439 | BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); | 457 | BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); |
440 | } | 458 | } |
441 | 459 | ||
442 | static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | ||
443 | struct rpc_clnt *clnt, | ||
444 | const char *service_name) | ||
445 | { | ||
446 | struct net *net = rpc_net_ns(clnt); | ||
447 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
448 | |||
449 | if (sn->pipe_version == 0) | ||
450 | gss_encode_v0_msg(gss_msg); | ||
451 | else /* pipe_version == 1 */ | ||
452 | gss_encode_v1_msg(gss_msg, clnt, service_name); | ||
453 | } | ||
454 | |||
455 | static struct gss_upcall_msg * | 460 | static struct gss_upcall_msg * |
456 | gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | 461 | gss_alloc_msg(struct gss_auth *gss_auth, |
457 | kuid_t uid, const char *service_name) | 462 | kuid_t uid, const char *service_name) |
458 | { | 463 | { |
459 | struct gss_upcall_msg *gss_msg; | 464 | struct gss_upcall_msg *gss_msg; |
@@ -462,31 +467,36 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
462 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 467 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
463 | if (gss_msg == NULL) | 468 | if (gss_msg == NULL) |
464 | return ERR_PTR(-ENOMEM); | 469 | return ERR_PTR(-ENOMEM); |
465 | vers = get_pipe_version(rpc_net_ns(clnt)); | 470 | vers = get_pipe_version(gss_auth->net); |
466 | if (vers < 0) { | 471 | if (vers < 0) { |
467 | kfree(gss_msg); | 472 | kfree(gss_msg); |
468 | return ERR_PTR(vers); | 473 | return ERR_PTR(vers); |
469 | } | 474 | } |
470 | gss_msg->pipe = gss_auth->pipe[vers]; | 475 | gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; |
471 | INIT_LIST_HEAD(&gss_msg->list); | 476 | INIT_LIST_HEAD(&gss_msg->list); |
472 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 477 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
473 | init_waitqueue_head(&gss_msg->waitqueue); | 478 | init_waitqueue_head(&gss_msg->waitqueue); |
474 | atomic_set(&gss_msg->count, 1); | 479 | atomic_set(&gss_msg->count, 1); |
475 | gss_msg->uid = uid; | 480 | gss_msg->uid = uid; |
476 | gss_msg->auth = gss_auth; | 481 | gss_msg->auth = gss_auth; |
477 | gss_encode_msg(gss_msg, clnt, service_name); | 482 | switch (vers) { |
483 | case 0: | ||
484 | gss_encode_v0_msg(gss_msg); | ||
485 | default: | ||
486 | gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); | ||
487 | }; | ||
478 | return gss_msg; | 488 | return gss_msg; |
479 | } | 489 | } |
480 | 490 | ||
481 | static struct gss_upcall_msg * | 491 | static struct gss_upcall_msg * |
482 | gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred) | 492 | gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) |
483 | { | 493 | { |
484 | struct gss_cred *gss_cred = container_of(cred, | 494 | struct gss_cred *gss_cred = container_of(cred, |
485 | struct gss_cred, gc_base); | 495 | struct gss_cred, gc_base); |
486 | struct gss_upcall_msg *gss_new, *gss_msg; | 496 | struct gss_upcall_msg *gss_new, *gss_msg; |
487 | kuid_t uid = cred->cr_uid; | 497 | kuid_t uid = cred->cr_uid; |
488 | 498 | ||
489 | gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal); | 499 | gss_new = gss_alloc_msg(gss_auth, uid, gss_cred->gc_principal); |
490 | if (IS_ERR(gss_new)) | 500 | if (IS_ERR(gss_new)) |
491 | return gss_new; | 501 | return gss_new; |
492 | gss_msg = gss_add_msg(gss_new); | 502 | gss_msg = gss_add_msg(gss_new); |
@@ -527,7 +537,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
527 | 537 | ||
528 | dprintk("RPC: %5u %s for uid %u\n", | 538 | dprintk("RPC: %5u %s for uid %u\n", |
529 | task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); | 539 | task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
530 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); | 540 | gss_msg = gss_setup_upcall(gss_auth, cred); |
531 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 541 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
532 | /* XXX: warning on the first, under the assumption we | 542 | /* XXX: warning on the first, under the assumption we |
533 | * shouldn't normally hit this case on a refresh. */ | 543 | * shouldn't normally hit this case on a refresh. */ |
@@ -566,7 +576,7 @@ out: | |||
566 | static inline int | 576 | static inline int |
567 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 577 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
568 | { | 578 | { |
569 | struct net *net = rpc_net_ns(gss_auth->client); | 579 | struct net *net = gss_auth->net; |
570 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 580 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
571 | struct rpc_pipe *pipe; | 581 | struct rpc_pipe *pipe; |
572 | struct rpc_cred *cred = &gss_cred->gc_base; | 582 | struct rpc_cred *cred = &gss_cred->gc_base; |
@@ -583,7 +593,7 @@ retry: | |||
583 | timeout = 15 * HZ; | 593 | timeout = 15 * HZ; |
584 | if (!sn->gssd_running) | 594 | if (!sn->gssd_running) |
585 | timeout = HZ >> 2; | 595 | timeout = HZ >> 2; |
586 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 596 | gss_msg = gss_setup_upcall(gss_auth, cred); |
587 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 597 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
588 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 598 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
589 | sn->pipe_version >= 0, timeout); | 599 | sn->pipe_version >= 0, timeout); |
@@ -797,83 +807,153 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
797 | } | 807 | } |
798 | } | 808 | } |
799 | 809 | ||
800 | static void gss_pipes_dentries_destroy(struct rpc_auth *auth) | 810 | static void gss_pipe_dentry_destroy(struct dentry *dir, |
811 | struct rpc_pipe_dir_object *pdo) | ||
801 | { | 812 | { |
802 | struct gss_auth *gss_auth; | 813 | struct gss_pipe *gss_pipe = pdo->pdo_data; |
814 | struct rpc_pipe *pipe = gss_pipe->pipe; | ||
803 | 815 | ||
804 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 816 | if (pipe->dentry != NULL) { |
805 | if (gss_auth->pipe[0]->dentry) | 817 | rpc_unlink(pipe->dentry); |
806 | rpc_unlink(gss_auth->pipe[0]->dentry); | 818 | pipe->dentry = NULL; |
807 | if (gss_auth->pipe[1]->dentry) | 819 | } |
808 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
809 | } | 820 | } |
810 | 821 | ||
811 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | 822 | static int gss_pipe_dentry_create(struct dentry *dir, |
823 | struct rpc_pipe_dir_object *pdo) | ||
812 | { | 824 | { |
813 | int err; | 825 | struct gss_pipe *p = pdo->pdo_data; |
814 | struct gss_auth *gss_auth; | 826 | struct dentry *dentry; |
815 | struct rpc_clnt *clnt; | ||
816 | 827 | ||
817 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 828 | dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe); |
818 | clnt = gss_auth->client; | 829 | if (IS_ERR(dentry)) |
819 | 830 | return PTR_ERR(dentry); | |
820 | gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | 831 | p->pipe->dentry = dentry; |
821 | "gssd", | ||
822 | clnt, gss_auth->pipe[1]); | ||
823 | if (IS_ERR(gss_auth->pipe[1]->dentry)) | ||
824 | return PTR_ERR(gss_auth->pipe[1]->dentry); | ||
825 | gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
826 | gss_auth->mech->gm_name, | ||
827 | clnt, gss_auth->pipe[0]); | ||
828 | if (IS_ERR(gss_auth->pipe[0]->dentry)) { | ||
829 | err = PTR_ERR(gss_auth->pipe[0]->dentry); | ||
830 | goto err_unlink_pipe_1; | ||
831 | } | ||
832 | return 0; | 832 | return 0; |
833 | } | ||
833 | 834 | ||
834 | err_unlink_pipe_1: | 835 | static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = { |
835 | rpc_unlink(gss_auth->pipe[1]->dentry); | 836 | .create = gss_pipe_dentry_create, |
836 | return err; | 837 | .destroy = gss_pipe_dentry_destroy, |
838 | }; | ||
839 | |||
840 | static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt, | ||
841 | const char *name, | ||
842 | const struct rpc_pipe_ops *upcall_ops) | ||
843 | { | ||
844 | struct gss_pipe *p; | ||
845 | int err = -ENOMEM; | ||
846 | |||
847 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
848 | if (p == NULL) | ||
849 | goto err; | ||
850 | p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | ||
851 | if (IS_ERR(p->pipe)) { | ||
852 | err = PTR_ERR(p->pipe); | ||
853 | goto err_free_gss_pipe; | ||
854 | } | ||
855 | p->name = name; | ||
856 | p->clnt = clnt; | ||
857 | kref_init(&p->kref); | ||
858 | rpc_init_pipe_dir_object(&p->pdo, | ||
859 | &gss_pipe_dir_object_ops, | ||
860 | p); | ||
861 | return p; | ||
862 | err_free_gss_pipe: | ||
863 | kfree(p); | ||
864 | err: | ||
865 | return ERR_PTR(err); | ||
866 | } | ||
867 | |||
868 | struct gss_alloc_pdo { | ||
869 | struct rpc_clnt *clnt; | ||
870 | const char *name; | ||
871 | const struct rpc_pipe_ops *upcall_ops; | ||
872 | }; | ||
873 | |||
874 | static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data) | ||
875 | { | ||
876 | struct gss_pipe *gss_pipe; | ||
877 | struct gss_alloc_pdo *args = data; | ||
878 | |||
879 | if (pdo->pdo_ops != &gss_pipe_dir_object_ops) | ||
880 | return 0; | ||
881 | gss_pipe = container_of(pdo, struct gss_pipe, pdo); | ||
882 | if (strcmp(gss_pipe->name, args->name) != 0) | ||
883 | return 0; | ||
884 | if (!kref_get_unless_zero(&gss_pipe->kref)) | ||
885 | return 0; | ||
886 | return 1; | ||
837 | } | 887 | } |
838 | 888 | ||
839 | static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, | 889 | static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data) |
840 | struct rpc_auth *auth) | 890 | { |
891 | struct gss_pipe *gss_pipe; | ||
892 | struct gss_alloc_pdo *args = data; | ||
893 | |||
894 | gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops); | ||
895 | if (!IS_ERR(gss_pipe)) | ||
896 | return &gss_pipe->pdo; | ||
897 | return NULL; | ||
898 | } | ||
899 | |||
900 | static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt, | ||
901 | const char *name, | ||
902 | const struct rpc_pipe_ops *upcall_ops) | ||
841 | { | 903 | { |
842 | struct net *net = rpc_net_ns(clnt); | 904 | struct net *net = rpc_net_ns(clnt); |
843 | struct super_block *sb; | 905 | struct rpc_pipe_dir_object *pdo; |
906 | struct gss_alloc_pdo args = { | ||
907 | .clnt = clnt, | ||
908 | .name = name, | ||
909 | .upcall_ops = upcall_ops, | ||
910 | }; | ||
844 | 911 | ||
845 | sb = rpc_get_sb_net(net); | 912 | pdo = rpc_find_or_alloc_pipe_dir_object(net, |
846 | if (sb) { | 913 | &clnt->cl_pipedir_objects, |
847 | if (clnt->cl_dentry) | 914 | gss_pipe_match_pdo, |
848 | gss_pipes_dentries_destroy(auth); | 915 | gss_pipe_alloc_pdo, |
849 | rpc_put_sb_net(net); | 916 | &args); |
850 | } | 917 | if (pdo != NULL) |
918 | return container_of(pdo, struct gss_pipe, pdo); | ||
919 | return ERR_PTR(-ENOMEM); | ||
851 | } | 920 | } |
852 | 921 | ||
853 | static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, | 922 | static void __gss_pipe_free(struct gss_pipe *p) |
854 | struct rpc_auth *auth) | ||
855 | { | 923 | { |
924 | struct rpc_clnt *clnt = p->clnt; | ||
856 | struct net *net = rpc_net_ns(clnt); | 925 | struct net *net = rpc_net_ns(clnt); |
857 | struct super_block *sb; | ||
858 | int err = 0; | ||
859 | 926 | ||
860 | sb = rpc_get_sb_net(net); | 927 | rpc_remove_pipe_dir_object(net, |
861 | if (sb) { | 928 | &clnt->cl_pipedir_objects, |
862 | if (clnt->cl_dentry) | 929 | &p->pdo); |
863 | err = gss_pipes_dentries_create(auth); | 930 | rpc_destroy_pipe_data(p->pipe); |
864 | rpc_put_sb_net(net); | 931 | kfree(p); |
865 | } | 932 | } |
866 | return err; | 933 | |
934 | static void __gss_pipe_release(struct kref *kref) | ||
935 | { | ||
936 | struct gss_pipe *p = container_of(kref, struct gss_pipe, kref); | ||
937 | |||
938 | __gss_pipe_free(p); | ||
939 | } | ||
940 | |||
941 | static void gss_pipe_free(struct gss_pipe *p) | ||
942 | { | ||
943 | if (p != NULL) | ||
944 | kref_put(&p->kref, __gss_pipe_release); | ||
867 | } | 945 | } |
868 | 946 | ||
869 | /* | 947 | /* |
870 | * NOTE: we have the opportunity to use different | 948 | * NOTE: we have the opportunity to use different |
871 | * parameters based on the input flavor (which must be a pseudoflavor) | 949 | * parameters based on the input flavor (which must be a pseudoflavor) |
872 | */ | 950 | */ |
873 | static struct rpc_auth * | 951 | static struct gss_auth * |
874 | gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 952 | gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
875 | { | 953 | { |
954 | rpc_authflavor_t flavor = args->pseudoflavor; | ||
876 | struct gss_auth *gss_auth; | 955 | struct gss_auth *gss_auth; |
956 | struct gss_pipe *gss_pipe; | ||
877 | struct rpc_auth * auth; | 957 | struct rpc_auth * auth; |
878 | int err = -ENOMEM; /* XXX? */ | 958 | int err = -ENOMEM; /* XXX? */ |
879 | 959 | ||
@@ -883,12 +963,20 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
883 | return ERR_PTR(err); | 963 | return ERR_PTR(err); |
884 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) | 964 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) |
885 | goto out_dec; | 965 | goto out_dec; |
966 | INIT_HLIST_NODE(&gss_auth->hash); | ||
967 | gss_auth->target_name = NULL; | ||
968 | if (args->target_name) { | ||
969 | gss_auth->target_name = kstrdup(args->target_name, GFP_KERNEL); | ||
970 | if (gss_auth->target_name == NULL) | ||
971 | goto err_free; | ||
972 | } | ||
886 | gss_auth->client = clnt; | 973 | gss_auth->client = clnt; |
974 | gss_auth->net = get_net(rpc_net_ns(clnt)); | ||
887 | err = -EINVAL; | 975 | err = -EINVAL; |
888 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); | 976 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); |
889 | if (!gss_auth->mech) { | 977 | if (!gss_auth->mech) { |
890 | dprintk("RPC: Pseudoflavor %d not found!\n", flavor); | 978 | dprintk("RPC: Pseudoflavor %d not found!\n", flavor); |
891 | goto err_free; | 979 | goto err_put_net; |
892 | } | 980 | } |
893 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); | 981 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
894 | if (gss_auth->service == 0) | 982 | if (gss_auth->service == 0) |
@@ -901,42 +989,41 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
901 | atomic_set(&auth->au_count, 1); | 989 | atomic_set(&auth->au_count, 1); |
902 | kref_init(&gss_auth->kref); | 990 | kref_init(&gss_auth->kref); |
903 | 991 | ||
992 | err = rpcauth_init_credcache(auth); | ||
993 | if (err) | ||
994 | goto err_put_mech; | ||
904 | /* | 995 | /* |
905 | * Note: if we created the old pipe first, then someone who | 996 | * Note: if we created the old pipe first, then someone who |
906 | * examined the directory at the right moment might conclude | 997 | * examined the directory at the right moment might conclude |
907 | * that we supported only the old pipe. So we instead create | 998 | * that we supported only the old pipe. So we instead create |
908 | * the new pipe first. | 999 | * the new pipe first. |
909 | */ | 1000 | */ |
910 | gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1, | 1001 | gss_pipe = gss_pipe_get(clnt, "gssd", &gss_upcall_ops_v1); |
911 | RPC_PIPE_WAIT_FOR_OPEN); | 1002 | if (IS_ERR(gss_pipe)) { |
912 | if (IS_ERR(gss_auth->pipe[1])) { | 1003 | err = PTR_ERR(gss_pipe); |
913 | err = PTR_ERR(gss_auth->pipe[1]); | 1004 | goto err_destroy_credcache; |
914 | goto err_put_mech; | ||
915 | } | 1005 | } |
1006 | gss_auth->gss_pipe[1] = gss_pipe; | ||
916 | 1007 | ||
917 | gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0, | 1008 | gss_pipe = gss_pipe_get(clnt, gss_auth->mech->gm_name, |
918 | RPC_PIPE_WAIT_FOR_OPEN); | 1009 | &gss_upcall_ops_v0); |
919 | if (IS_ERR(gss_auth->pipe[0])) { | 1010 | if (IS_ERR(gss_pipe)) { |
920 | err = PTR_ERR(gss_auth->pipe[0]); | 1011 | err = PTR_ERR(gss_pipe); |
921 | goto err_destroy_pipe_1; | 1012 | goto err_destroy_pipe_1; |
922 | } | 1013 | } |
923 | err = gss_pipes_dentries_create_net(clnt, auth); | 1014 | gss_auth->gss_pipe[0] = gss_pipe; |
924 | if (err) | ||
925 | goto err_destroy_pipe_0; | ||
926 | err = rpcauth_init_credcache(auth); | ||
927 | if (err) | ||
928 | goto err_unlink_pipes; | ||
929 | 1015 | ||
930 | return auth; | 1016 | return gss_auth; |
931 | err_unlink_pipes: | ||
932 | gss_pipes_dentries_destroy_net(clnt, auth); | ||
933 | err_destroy_pipe_0: | ||
934 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | ||
935 | err_destroy_pipe_1: | 1017 | err_destroy_pipe_1: |
936 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | 1018 | gss_pipe_free(gss_auth->gss_pipe[1]); |
1019 | err_destroy_credcache: | ||
1020 | rpcauth_destroy_credcache(auth); | ||
937 | err_put_mech: | 1021 | err_put_mech: |
938 | gss_mech_put(gss_auth->mech); | 1022 | gss_mech_put(gss_auth->mech); |
1023 | err_put_net: | ||
1024 | put_net(gss_auth->net); | ||
939 | err_free: | 1025 | err_free: |
1026 | kfree(gss_auth->target_name); | ||
940 | kfree(gss_auth); | 1027 | kfree(gss_auth); |
941 | out_dec: | 1028 | out_dec: |
942 | module_put(THIS_MODULE); | 1029 | module_put(THIS_MODULE); |
@@ -946,10 +1033,11 @@ out_dec: | |||
946 | static void | 1033 | static void |
947 | gss_free(struct gss_auth *gss_auth) | 1034 | gss_free(struct gss_auth *gss_auth) |
948 | { | 1035 | { |
949 | gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth); | 1036 | gss_pipe_free(gss_auth->gss_pipe[0]); |
950 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | 1037 | gss_pipe_free(gss_auth->gss_pipe[1]); |
951 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
952 | gss_mech_put(gss_auth->mech); | 1038 | gss_mech_put(gss_auth->mech); |
1039 | put_net(gss_auth->net); | ||
1040 | kfree(gss_auth->target_name); | ||
953 | 1041 | ||
954 | kfree(gss_auth); | 1042 | kfree(gss_auth); |
955 | module_put(THIS_MODULE); | 1043 | module_put(THIS_MODULE); |
@@ -966,17 +1054,101 @@ gss_free_callback(struct kref *kref) | |||
966 | static void | 1054 | static void |
967 | gss_destroy(struct rpc_auth *auth) | 1055 | gss_destroy(struct rpc_auth *auth) |
968 | { | 1056 | { |
969 | struct gss_auth *gss_auth; | 1057 | struct gss_auth *gss_auth = container_of(auth, |
1058 | struct gss_auth, rpc_auth); | ||
970 | 1059 | ||
971 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", | 1060 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", |
972 | auth, auth->au_flavor); | 1061 | auth, auth->au_flavor); |
973 | 1062 | ||
1063 | if (hash_hashed(&gss_auth->hash)) { | ||
1064 | spin_lock(&gss_auth_hash_lock); | ||
1065 | hash_del(&gss_auth->hash); | ||
1066 | spin_unlock(&gss_auth_hash_lock); | ||
1067 | } | ||
1068 | |||
1069 | gss_pipe_free(gss_auth->gss_pipe[0]); | ||
1070 | gss_auth->gss_pipe[0] = NULL; | ||
1071 | gss_pipe_free(gss_auth->gss_pipe[1]); | ||
1072 | gss_auth->gss_pipe[1] = NULL; | ||
974 | rpcauth_destroy_credcache(auth); | 1073 | rpcauth_destroy_credcache(auth); |
975 | 1074 | ||
976 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
977 | kref_put(&gss_auth->kref, gss_free_callback); | 1075 | kref_put(&gss_auth->kref, gss_free_callback); |
978 | } | 1076 | } |
979 | 1077 | ||
1078 | static struct gss_auth * | ||
1079 | gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args, | ||
1080 | struct rpc_clnt *clnt, | ||
1081 | struct gss_auth *new) | ||
1082 | { | ||
1083 | struct gss_auth *gss_auth; | ||
1084 | unsigned long hashval = (unsigned long)clnt; | ||
1085 | |||
1086 | spin_lock(&gss_auth_hash_lock); | ||
1087 | hash_for_each_possible(gss_auth_hash_table, | ||
1088 | gss_auth, | ||
1089 | hash, | ||
1090 | hashval) { | ||
1091 | if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor) | ||
1092 | continue; | ||
1093 | if (gss_auth->target_name != args->target_name) { | ||
1094 | if (gss_auth->target_name == NULL) | ||
1095 | continue; | ||
1096 | if (args->target_name == NULL) | ||
1097 | continue; | ||
1098 | if (strcmp(gss_auth->target_name, args->target_name)) | ||
1099 | continue; | ||
1100 | } | ||
1101 | if (!atomic_inc_not_zero(&gss_auth->rpc_auth.au_count)) | ||
1102 | continue; | ||
1103 | goto out; | ||
1104 | } | ||
1105 | if (new) | ||
1106 | hash_add(gss_auth_hash_table, &new->hash, hashval); | ||
1107 | gss_auth = new; | ||
1108 | out: | ||
1109 | spin_unlock(&gss_auth_hash_lock); | ||
1110 | return gss_auth; | ||
1111 | } | ||
1112 | |||
1113 | static struct gss_auth * | ||
1114 | gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | ||
1115 | { | ||
1116 | struct gss_auth *gss_auth; | ||
1117 | struct gss_auth *new; | ||
1118 | |||
1119 | gss_auth = gss_auth_find_or_add_hashed(args, clnt, NULL); | ||
1120 | if (gss_auth != NULL) | ||
1121 | goto out; | ||
1122 | new = gss_create_new(args, clnt); | ||
1123 | if (IS_ERR(new)) | ||
1124 | return new; | ||
1125 | gss_auth = gss_auth_find_or_add_hashed(args, clnt, new); | ||
1126 | if (gss_auth != new) | ||
1127 | gss_destroy(&new->rpc_auth); | ||
1128 | out: | ||
1129 | return gss_auth; | ||
1130 | } | ||
1131 | |||
1132 | static struct rpc_auth * | ||
1133 | gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | ||
1134 | { | ||
1135 | struct gss_auth *gss_auth; | ||
1136 | struct rpc_xprt *xprt = rcu_access_pointer(clnt->cl_xprt); | ||
1137 | |||
1138 | while (clnt != clnt->cl_parent) { | ||
1139 | struct rpc_clnt *parent = clnt->cl_parent; | ||
1140 | /* Find the original parent for this transport */ | ||
1141 | if (rcu_access_pointer(parent->cl_xprt) != xprt) | ||
1142 | break; | ||
1143 | clnt = parent; | ||
1144 | } | ||
1145 | |||
1146 | gss_auth = gss_create_hashed(args, clnt); | ||
1147 | if (IS_ERR(gss_auth)) | ||
1148 | return ERR_CAST(gss_auth); | ||
1149 | return &gss_auth->rpc_auth; | ||
1150 | } | ||
1151 | |||
980 | /* | 1152 | /* |
981 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call | 1153 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call |
982 | * to the server with the GSS control procedure field set to | 1154 | * to the server with the GSS control procedure field set to |
@@ -1126,10 +1298,32 @@ gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) | |||
1126 | return err; | 1298 | return err; |
1127 | } | 1299 | } |
1128 | 1300 | ||
1301 | /* | ||
1302 | * Returns -EACCES if GSS context is NULL or will expire within the | ||
1303 | * timeout (miliseconds) | ||
1304 | */ | ||
1305 | static int | ||
1306 | gss_key_timeout(struct rpc_cred *rc) | ||
1307 | { | ||
1308 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | ||
1309 | unsigned long now = jiffies; | ||
1310 | unsigned long expire; | ||
1311 | |||
1312 | if (gss_cred->gc_ctx == NULL) | ||
1313 | return -EACCES; | ||
1314 | |||
1315 | expire = gss_cred->gc_ctx->gc_expiry - (gss_key_expire_timeo * HZ); | ||
1316 | |||
1317 | if (time_after(now, expire)) | ||
1318 | return -EACCES; | ||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1129 | static int | 1322 | static int |
1130 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | 1323 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
1131 | { | 1324 | { |
1132 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1325 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1326 | int ret; | ||
1133 | 1327 | ||
1134 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) | 1328 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
1135 | goto out; | 1329 | goto out; |
@@ -1142,11 +1336,26 @@ out: | |||
1142 | if (acred->principal != NULL) { | 1336 | if (acred->principal != NULL) { |
1143 | if (gss_cred->gc_principal == NULL) | 1337 | if (gss_cred->gc_principal == NULL) |
1144 | return 0; | 1338 | return 0; |
1145 | return strcmp(acred->principal, gss_cred->gc_principal) == 0; | 1339 | ret = strcmp(acred->principal, gss_cred->gc_principal) == 0; |
1340 | goto check_expire; | ||
1146 | } | 1341 | } |
1147 | if (gss_cred->gc_principal != NULL) | 1342 | if (gss_cred->gc_principal != NULL) |
1148 | return 0; | 1343 | return 0; |
1149 | return uid_eq(rc->cr_uid, acred->uid); | 1344 | ret = uid_eq(rc->cr_uid, acred->uid); |
1345 | |||
1346 | check_expire: | ||
1347 | if (ret == 0) | ||
1348 | return ret; | ||
1349 | |||
1350 | /* Notify acred users of GSS context expiration timeout */ | ||
1351 | if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags) && | ||
1352 | (gss_key_timeout(rc) != 0)) { | ||
1353 | /* test will now be done from generic cred */ | ||
1354 | test_and_clear_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); | ||
1355 | /* tell NFS layer that key will expire soon */ | ||
1356 | set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
1357 | } | ||
1358 | return ret; | ||
1150 | } | 1359 | } |
1151 | 1360 | ||
1152 | /* | 1361 | /* |
@@ -1292,6 +1501,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1292 | struct xdr_netobj mic; | 1501 | struct xdr_netobj mic; |
1293 | u32 flav,len; | 1502 | u32 flav,len; |
1294 | u32 maj_stat; | 1503 | u32 maj_stat; |
1504 | __be32 *ret = ERR_PTR(-EIO); | ||
1295 | 1505 | ||
1296 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1506 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); |
1297 | 1507 | ||
@@ -1307,6 +1517,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1307 | mic.data = (u8 *)p; | 1517 | mic.data = (u8 *)p; |
1308 | mic.len = len; | 1518 | mic.len = len; |
1309 | 1519 | ||
1520 | ret = ERR_PTR(-EACCES); | ||
1310 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 1521 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1311 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1522 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1312 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1523 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
@@ -1324,8 +1535,9 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1324 | return p + XDR_QUADLEN(len); | 1535 | return p + XDR_QUADLEN(len); |
1325 | out_bad: | 1536 | out_bad: |
1326 | gss_put_ctx(ctx); | 1537 | gss_put_ctx(ctx); |
1327 | dprintk("RPC: %5u %s failed.\n", task->tk_pid, __func__); | 1538 | dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__, |
1328 | return NULL; | 1539 | PTR_ERR(ret)); |
1540 | return ret; | ||
1329 | } | 1541 | } |
1330 | 1542 | ||
1331 | static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, | 1543 | static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, |
@@ -1657,8 +1869,6 @@ static const struct rpc_authops authgss_ops = { | |||
1657 | .destroy = gss_destroy, | 1869 | .destroy = gss_destroy, |
1658 | .lookup_cred = gss_lookup_cred, | 1870 | .lookup_cred = gss_lookup_cred, |
1659 | .crcreate = gss_create_cred, | 1871 | .crcreate = gss_create_cred, |
1660 | .pipes_create = gss_pipes_dentries_create, | ||
1661 | .pipes_destroy = gss_pipes_dentries_destroy, | ||
1662 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | 1872 | .list_pseudoflavors = gss_mech_list_pseudoflavors, |
1663 | .info2flavor = gss_mech_info2flavor, | 1873 | .info2flavor = gss_mech_info2flavor, |
1664 | .flavor2info = gss_mech_flavor2info, | 1874 | .flavor2info = gss_mech_flavor2info, |
@@ -1675,6 +1885,7 @@ static const struct rpc_credops gss_credops = { | |||
1675 | .crvalidate = gss_validate, | 1885 | .crvalidate = gss_validate, |
1676 | .crwrap_req = gss_wrap_req, | 1886 | .crwrap_req = gss_wrap_req, |
1677 | .crunwrap_resp = gss_unwrap_resp, | 1887 | .crunwrap_resp = gss_unwrap_resp, |
1888 | .crkey_timeout = gss_key_timeout, | ||
1678 | }; | 1889 | }; |
1679 | 1890 | ||
1680 | static const struct rpc_credops gss_nullops = { | 1891 | static const struct rpc_credops gss_nullops = { |
@@ -1762,5 +1973,12 @@ module_param_named(expired_cred_retry_delay, | |||
1762 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " | 1973 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " |
1763 | "the RPC engine retries an expired credential"); | 1974 | "the RPC engine retries an expired credential"); |
1764 | 1975 | ||
1976 | module_param_named(key_expire_timeo, | ||
1977 | gss_key_expire_timeo, | ||
1978 | uint, 0644); | ||
1979 | MODULE_PARM_DESC(key_expire_timeo, "Time (in seconds) at the end of a " | ||
1980 | "credential keys lifetime where the NFS layer cleans up " | ||
1981 | "prior to key expiration"); | ||
1982 | |||
1765 | module_init(init_rpcsec_gss) | 1983 | module_init(init_rpcsec_gss) |
1766 | module_exit(exit_rpcsec_gss) | 1984 | module_exit(exit_rpcsec_gss) |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index a5c36c01707b..f0ebe07978a2 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -18,7 +18,7 @@ static struct rpc_auth null_auth; | |||
18 | static struct rpc_cred null_cred; | 18 | static struct rpc_cred null_cred; |
19 | 19 | ||
20 | static struct rpc_auth * | 20 | static struct rpc_auth * |
21 | nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 21 | nul_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
22 | { | 22 | { |
23 | atomic_inc(&null_auth.au_count); | 23 | atomic_inc(&null_auth.au_count); |
24 | return &null_auth; | 24 | return &null_auth; |
@@ -88,13 +88,13 @@ nul_validate(struct rpc_task *task, __be32 *p) | |||
88 | flavor = ntohl(*p++); | 88 | flavor = ntohl(*p++); |
89 | if (flavor != RPC_AUTH_NULL) { | 89 | if (flavor != RPC_AUTH_NULL) { |
90 | printk("RPC: bad verf flavor: %u\n", flavor); | 90 | printk("RPC: bad verf flavor: %u\n", flavor); |
91 | return NULL; | 91 | return ERR_PTR(-EIO); |
92 | } | 92 | } |
93 | 93 | ||
94 | size = ntohl(*p++); | 94 | size = ntohl(*p++); |
95 | if (size != 0) { | 95 | if (size != 0) { |
96 | printk("RPC: bad verf size: %u\n", size); | 96 | printk("RPC: bad verf size: %u\n", size); |
97 | return NULL; | 97 | return ERR_PTR(-EIO); |
98 | } | 98 | } |
99 | 99 | ||
100 | return p; | 100 | return p; |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index dc37021fc3e5..d5d692366294 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -33,7 +33,7 @@ static struct rpc_auth unix_auth; | |||
33 | static const struct rpc_credops unix_credops; | 33 | static const struct rpc_credops unix_credops; |
34 | 34 | ||
35 | static struct rpc_auth * | 35 | static struct rpc_auth * |
36 | unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 36 | unx_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
37 | { | 37 | { |
38 | dprintk("RPC: creating UNIX authenticator for client %p\n", | 38 | dprintk("RPC: creating UNIX authenticator for client %p\n", |
39 | clnt); | 39 | clnt); |
@@ -192,13 +192,13 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
192 | flavor != RPC_AUTH_UNIX && | 192 | flavor != RPC_AUTH_UNIX && |
193 | flavor != RPC_AUTH_SHORT) { | 193 | flavor != RPC_AUTH_SHORT) { |
194 | printk("RPC: bad verf flavor: %u\n", flavor); | 194 | printk("RPC: bad verf flavor: %u\n", flavor); |
195 | return NULL; | 195 | return ERR_PTR(-EIO); |
196 | } | 196 | } |
197 | 197 | ||
198 | size = ntohl(*p++); | 198 | size = ntohl(*p++); |
199 | if (size > RPC_MAX_AUTH_SIZE) { | 199 | if (size > RPC_MAX_AUTH_SIZE) { |
200 | printk("RPC: giant verf size: %u\n", size); | 200 | printk("RPC: giant verf size: %u\n", size); |
201 | return NULL; | 201 | return ERR_PTR(-EIO); |
202 | } | 202 | } |
203 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; | 203 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; |
204 | p += (size >> 2); | 204 | p += (size >> 2); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index ecbc4e3d83ad..77479606a971 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -102,12 +102,7 @@ static void rpc_unregister_client(struct rpc_clnt *clnt) | |||
102 | 102 | ||
103 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 103 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
104 | { | 104 | { |
105 | if (clnt->cl_dentry) { | 105 | rpc_remove_client_dir(clnt); |
106 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | ||
107 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | ||
108 | rpc_remove_client_dir(clnt->cl_dentry); | ||
109 | } | ||
110 | clnt->cl_dentry = NULL; | ||
111 | } | 106 | } |
112 | 107 | ||
113 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 108 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
@@ -123,10 +118,10 @@ static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | |||
123 | } | 118 | } |
124 | 119 | ||
125 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | 120 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, |
126 | struct rpc_clnt *clnt, | 121 | struct rpc_clnt *clnt) |
127 | const char *dir_name) | ||
128 | { | 122 | { |
129 | static uint32_t clntid; | 123 | static uint32_t clntid; |
124 | const char *dir_name = clnt->cl_program->pipe_dir_name; | ||
130 | char name[15]; | 125 | char name[15]; |
131 | struct dentry *dir, *dentry; | 126 | struct dentry *dir, *dentry; |
132 | 127 | ||
@@ -153,28 +148,35 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
153 | } | 148 | } |
154 | 149 | ||
155 | static int | 150 | static int |
156 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name, | 151 | rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt) |
157 | struct super_block *pipefs_sb) | ||
158 | { | 152 | { |
159 | struct dentry *dentry; | 153 | struct dentry *dentry; |
160 | 154 | ||
161 | clnt->cl_dentry = NULL; | 155 | if (clnt->cl_program->pipe_dir_name != NULL) { |
162 | if (dir_name == NULL) | 156 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt); |
163 | return 0; | 157 | if (IS_ERR(dentry)) |
164 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 158 | return PTR_ERR(dentry); |
165 | if (IS_ERR(dentry)) | 159 | } |
166 | return PTR_ERR(dentry); | ||
167 | clnt->cl_dentry = dentry; | ||
168 | return 0; | 160 | return 0; |
169 | } | 161 | } |
170 | 162 | ||
171 | static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) | 163 | static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) |
172 | { | 164 | { |
173 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | 165 | if (clnt->cl_program->pipe_dir_name == NULL) |
174 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | ||
175 | return 1; | ||
176 | if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0) | ||
177 | return 1; | 166 | return 1; |
167 | |||
168 | switch (event) { | ||
169 | case RPC_PIPEFS_MOUNT: | ||
170 | if (clnt->cl_pipedir_objects.pdh_dentry != NULL) | ||
171 | return 1; | ||
172 | if (atomic_read(&clnt->cl_count) == 0) | ||
173 | return 1; | ||
174 | break; | ||
175 | case RPC_PIPEFS_UMOUNT: | ||
176 | if (clnt->cl_pipedir_objects.pdh_dentry == NULL) | ||
177 | return 1; | ||
178 | break; | ||
179 | } | ||
178 | return 0; | 180 | return 0; |
179 | } | 181 | } |
180 | 182 | ||
@@ -186,18 +188,11 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, | |||
186 | 188 | ||
187 | switch (event) { | 189 | switch (event) { |
188 | case RPC_PIPEFS_MOUNT: | 190 | case RPC_PIPEFS_MOUNT: |
189 | dentry = rpc_setup_pipedir_sb(sb, clnt, | 191 | dentry = rpc_setup_pipedir_sb(sb, clnt); |
190 | clnt->cl_program->pipe_dir_name); | ||
191 | if (!dentry) | 192 | if (!dentry) |
192 | return -ENOENT; | 193 | return -ENOENT; |
193 | if (IS_ERR(dentry)) | 194 | if (IS_ERR(dentry)) |
194 | return PTR_ERR(dentry); | 195 | return PTR_ERR(dentry); |
195 | clnt->cl_dentry = dentry; | ||
196 | if (clnt->cl_auth->au_ops->pipes_create) { | ||
197 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | ||
198 | if (err) | ||
199 | __rpc_clnt_remove_pipedir(clnt); | ||
200 | } | ||
201 | break; | 196 | break; |
202 | case RPC_PIPEFS_UMOUNT: | 197 | case RPC_PIPEFS_UMOUNT: |
203 | __rpc_clnt_remove_pipedir(clnt); | 198 | __rpc_clnt_remove_pipedir(clnt); |
@@ -230,8 +225,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
230 | 225 | ||
231 | spin_lock(&sn->rpc_client_lock); | 226 | spin_lock(&sn->rpc_client_lock); |
232 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 227 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
233 | if (clnt->cl_program->pipe_dir_name == NULL) | ||
234 | continue; | ||
235 | if (rpc_clnt_skip_event(clnt, event)) | 228 | if (rpc_clnt_skip_event(clnt, event)) |
236 | continue; | 229 | continue; |
237 | spin_unlock(&sn->rpc_client_lock); | 230 | spin_unlock(&sn->rpc_client_lock); |
@@ -282,7 +275,10 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
282 | static int rpc_client_register(const struct rpc_create_args *args, | 275 | static int rpc_client_register(const struct rpc_create_args *args, |
283 | struct rpc_clnt *clnt) | 276 | struct rpc_clnt *clnt) |
284 | { | 277 | { |
285 | const struct rpc_program *program = args->program; | 278 | struct rpc_auth_create_args auth_args = { |
279 | .pseudoflavor = args->authflavor, | ||
280 | .target_name = args->client_name, | ||
281 | }; | ||
286 | struct rpc_auth *auth; | 282 | struct rpc_auth *auth; |
287 | struct net *net = rpc_net_ns(clnt); | 283 | struct net *net = rpc_net_ns(clnt); |
288 | struct super_block *pipefs_sb; | 284 | struct super_block *pipefs_sb; |
@@ -290,7 +286,7 @@ static int rpc_client_register(const struct rpc_create_args *args, | |||
290 | 286 | ||
291 | pipefs_sb = rpc_get_sb_net(net); | 287 | pipefs_sb = rpc_get_sb_net(net); |
292 | if (pipefs_sb) { | 288 | if (pipefs_sb) { |
293 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb); | 289 | err = rpc_setup_pipedir(pipefs_sb, clnt); |
294 | if (err) | 290 | if (err) |
295 | goto out; | 291 | goto out; |
296 | } | 292 | } |
@@ -299,7 +295,7 @@ static int rpc_client_register(const struct rpc_create_args *args, | |||
299 | if (pipefs_sb) | 295 | if (pipefs_sb) |
300 | rpc_put_sb_net(net); | 296 | rpc_put_sb_net(net); |
301 | 297 | ||
302 | auth = rpcauth_create(args->authflavor, clnt); | 298 | auth = rpcauth_create(&auth_args, clnt); |
303 | if (IS_ERR(auth)) { | 299 | if (IS_ERR(auth)) { |
304 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | 300 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", |
305 | args->authflavor); | 301 | args->authflavor); |
@@ -317,7 +313,27 @@ out: | |||
317 | return err; | 313 | return err; |
318 | } | 314 | } |
319 | 315 | ||
320 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 316 | static DEFINE_IDA(rpc_clids); |
317 | |||
318 | static int rpc_alloc_clid(struct rpc_clnt *clnt) | ||
319 | { | ||
320 | int clid; | ||
321 | |||
322 | clid = ida_simple_get(&rpc_clids, 0, 0, GFP_KERNEL); | ||
323 | if (clid < 0) | ||
324 | return clid; | ||
325 | clnt->cl_clid = clid; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void rpc_free_clid(struct rpc_clnt *clnt) | ||
330 | { | ||
331 | ida_simple_remove(&rpc_clids, clnt->cl_clid); | ||
332 | } | ||
333 | |||
334 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | ||
335 | struct rpc_xprt *xprt, | ||
336 | struct rpc_clnt *parent) | ||
321 | { | 337 | { |
322 | const struct rpc_program *program = args->program; | 338 | const struct rpc_program *program = args->program; |
323 | const struct rpc_version *version; | 339 | const struct rpc_version *version; |
@@ -343,16 +359,20 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
343 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | 359 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
344 | if (!clnt) | 360 | if (!clnt) |
345 | goto out_err; | 361 | goto out_err; |
346 | clnt->cl_parent = clnt; | 362 | clnt->cl_parent = parent ? : clnt; |
363 | |||
364 | err = rpc_alloc_clid(clnt); | ||
365 | if (err) | ||
366 | goto out_no_clid; | ||
347 | 367 | ||
348 | rcu_assign_pointer(clnt->cl_xprt, xprt); | 368 | rcu_assign_pointer(clnt->cl_xprt, xprt); |
349 | clnt->cl_procinfo = version->procs; | 369 | clnt->cl_procinfo = version->procs; |
350 | clnt->cl_maxproc = version->nrprocs; | 370 | clnt->cl_maxproc = version->nrprocs; |
351 | clnt->cl_protname = program->name; | ||
352 | clnt->cl_prog = args->prognumber ? : program->number; | 371 | clnt->cl_prog = args->prognumber ? : program->number; |
353 | clnt->cl_vers = version->number; | 372 | clnt->cl_vers = version->number; |
354 | clnt->cl_stats = program->stats; | 373 | clnt->cl_stats = program->stats; |
355 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 374 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
375 | rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects); | ||
356 | err = -ENOMEM; | 376 | err = -ENOMEM; |
357 | if (clnt->cl_metrics == NULL) | 377 | if (clnt->cl_metrics == NULL) |
358 | goto out_no_stats; | 378 | goto out_no_stats; |
@@ -372,12 +392,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
372 | 392 | ||
373 | clnt->cl_rtt = &clnt->cl_rtt_default; | 393 | clnt->cl_rtt = &clnt->cl_rtt_default; |
374 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); | 394 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); |
375 | clnt->cl_principal = NULL; | ||
376 | if (args->client_name) { | ||
377 | clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL); | ||
378 | if (!clnt->cl_principal) | ||
379 | goto out_no_principal; | ||
380 | } | ||
381 | 395 | ||
382 | atomic_set(&clnt->cl_count, 1); | 396 | atomic_set(&clnt->cl_count, 1); |
383 | 397 | ||
@@ -387,13 +401,15 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
387 | err = rpc_client_register(args, clnt); | 401 | err = rpc_client_register(args, clnt); |
388 | if (err) | 402 | if (err) |
389 | goto out_no_path; | 403 | goto out_no_path; |
404 | if (parent) | ||
405 | atomic_inc(&parent->cl_count); | ||
390 | return clnt; | 406 | return clnt; |
391 | 407 | ||
392 | out_no_path: | 408 | out_no_path: |
393 | kfree(clnt->cl_principal); | ||
394 | out_no_principal: | ||
395 | rpc_free_iostats(clnt->cl_metrics); | 409 | rpc_free_iostats(clnt->cl_metrics); |
396 | out_no_stats: | 410 | out_no_stats: |
411 | rpc_free_clid(clnt); | ||
412 | out_no_clid: | ||
397 | kfree(clnt); | 413 | kfree(clnt); |
398 | out_err: | 414 | out_err: |
399 | rpciod_down(); | 415 | rpciod_down(); |
@@ -479,7 +495,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
479 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 495 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
480 | xprt->resvport = 0; | 496 | xprt->resvport = 0; |
481 | 497 | ||
482 | clnt = rpc_new_client(args, xprt); | 498 | clnt = rpc_new_client(args, xprt, NULL); |
483 | if (IS_ERR(clnt)) | 499 | if (IS_ERR(clnt)) |
484 | return clnt; | 500 | return clnt; |
485 | 501 | ||
@@ -526,15 +542,12 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
526 | goto out_err; | 542 | goto out_err; |
527 | args->servername = xprt->servername; | 543 | args->servername = xprt->servername; |
528 | 544 | ||
529 | new = rpc_new_client(args, xprt); | 545 | new = rpc_new_client(args, xprt, clnt); |
530 | if (IS_ERR(new)) { | 546 | if (IS_ERR(new)) { |
531 | err = PTR_ERR(new); | 547 | err = PTR_ERR(new); |
532 | goto out_err; | 548 | goto out_err; |
533 | } | 549 | } |
534 | 550 | ||
535 | atomic_inc(&clnt->cl_count); | ||
536 | new->cl_parent = clnt; | ||
537 | |||
538 | /* Turn off autobind on clones */ | 551 | /* Turn off autobind on clones */ |
539 | new->cl_autobind = 0; | 552 | new->cl_autobind = 0; |
540 | new->cl_softrtry = clnt->cl_softrtry; | 553 | new->cl_softrtry = clnt->cl_softrtry; |
@@ -561,7 +574,6 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) | |||
561 | .prognumber = clnt->cl_prog, | 574 | .prognumber = clnt->cl_prog, |
562 | .version = clnt->cl_vers, | 575 | .version = clnt->cl_vers, |
563 | .authflavor = clnt->cl_auth->au_flavor, | 576 | .authflavor = clnt->cl_auth->au_flavor, |
564 | .client_name = clnt->cl_principal, | ||
565 | }; | 577 | }; |
566 | return __rpc_clone_client(&args, clnt); | 578 | return __rpc_clone_client(&args, clnt); |
567 | } | 579 | } |
@@ -583,7 +595,6 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
583 | .prognumber = clnt->cl_prog, | 595 | .prognumber = clnt->cl_prog, |
584 | .version = clnt->cl_vers, | 596 | .version = clnt->cl_vers, |
585 | .authflavor = flavor, | 597 | .authflavor = flavor, |
586 | .client_name = clnt->cl_principal, | ||
587 | }; | 598 | }; |
588 | return __rpc_clone_client(&args, clnt); | 599 | return __rpc_clone_client(&args, clnt); |
589 | } | 600 | } |
@@ -629,7 +640,7 @@ void rpc_shutdown_client(struct rpc_clnt *clnt) | |||
629 | might_sleep(); | 640 | might_sleep(); |
630 | 641 | ||
631 | dprintk_rcu("RPC: shutting down %s client for %s\n", | 642 | dprintk_rcu("RPC: shutting down %s client for %s\n", |
632 | clnt->cl_protname, | 643 | clnt->cl_program->name, |
633 | rcu_dereference(clnt->cl_xprt)->servername); | 644 | rcu_dereference(clnt->cl_xprt)->servername); |
634 | 645 | ||
635 | while (!list_empty(&clnt->cl_tasks)) { | 646 | while (!list_empty(&clnt->cl_tasks)) { |
@@ -649,17 +660,17 @@ static void | |||
649 | rpc_free_client(struct rpc_clnt *clnt) | 660 | rpc_free_client(struct rpc_clnt *clnt) |
650 | { | 661 | { |
651 | dprintk_rcu("RPC: destroying %s client for %s\n", | 662 | dprintk_rcu("RPC: destroying %s client for %s\n", |
652 | clnt->cl_protname, | 663 | clnt->cl_program->name, |
653 | rcu_dereference(clnt->cl_xprt)->servername); | 664 | rcu_dereference(clnt->cl_xprt)->servername); |
654 | if (clnt->cl_parent != clnt) | 665 | if (clnt->cl_parent != clnt) |
655 | rpc_release_client(clnt->cl_parent); | 666 | rpc_release_client(clnt->cl_parent); |
656 | rpc_clnt_remove_pipedir(clnt); | 667 | rpc_clnt_remove_pipedir(clnt); |
657 | rpc_unregister_client(clnt); | 668 | rpc_unregister_client(clnt); |
658 | rpc_free_iostats(clnt->cl_metrics); | 669 | rpc_free_iostats(clnt->cl_metrics); |
659 | kfree(clnt->cl_principal); | ||
660 | clnt->cl_metrics = NULL; | 670 | clnt->cl_metrics = NULL; |
661 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); | 671 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); |
662 | rpciod_down(); | 672 | rpciod_down(); |
673 | rpc_free_clid(clnt); | ||
663 | kfree(clnt); | 674 | kfree(clnt); |
664 | } | 675 | } |
665 | 676 | ||
@@ -720,7 +731,6 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | |||
720 | .prognumber = program->number, | 731 | .prognumber = program->number, |
721 | .version = vers, | 732 | .version = vers, |
722 | .authflavor = old->cl_auth->au_flavor, | 733 | .authflavor = old->cl_auth->au_flavor, |
723 | .client_name = old->cl_principal, | ||
724 | }; | 734 | }; |
725 | struct rpc_clnt *clnt; | 735 | struct rpc_clnt *clnt; |
726 | int err; | 736 | int err; |
@@ -1299,7 +1309,7 @@ call_start(struct rpc_task *task) | |||
1299 | struct rpc_clnt *clnt = task->tk_client; | 1309 | struct rpc_clnt *clnt = task->tk_client; |
1300 | 1310 | ||
1301 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, | 1311 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, |
1302 | clnt->cl_protname, clnt->cl_vers, | 1312 | clnt->cl_program->name, clnt->cl_vers, |
1303 | rpc_proc_name(task), | 1313 | rpc_proc_name(task), |
1304 | (RPC_IS_ASYNC(task) ? "async" : "sync")); | 1314 | (RPC_IS_ASYNC(task) ? "async" : "sync")); |
1305 | 1315 | ||
@@ -1423,9 +1433,9 @@ call_refreshresult(struct rpc_task *task) | |||
1423 | return; | 1433 | return; |
1424 | case -ETIMEDOUT: | 1434 | case -ETIMEDOUT: |
1425 | rpc_delay(task, 3*HZ); | 1435 | rpc_delay(task, 3*HZ); |
1426 | case -EKEYEXPIRED: | ||
1427 | case -EAGAIN: | 1436 | case -EAGAIN: |
1428 | status = -EACCES; | 1437 | status = -EACCES; |
1438 | case -EKEYEXPIRED: | ||
1429 | if (!task->tk_cred_retry) | 1439 | if (!task->tk_cred_retry) |
1430 | break; | 1440 | break; |
1431 | task->tk_cred_retry--; | 1441 | task->tk_cred_retry--; |
@@ -1912,7 +1922,7 @@ call_status(struct rpc_task *task) | |||
1912 | default: | 1922 | default: |
1913 | if (clnt->cl_chatty) | 1923 | if (clnt->cl_chatty) |
1914 | printk("%s: RPC call returned error %d\n", | 1924 | printk("%s: RPC call returned error %d\n", |
1915 | clnt->cl_protname, -status); | 1925 | clnt->cl_program->name, -status); |
1916 | rpc_exit(task, status); | 1926 | rpc_exit(task, status); |
1917 | } | 1927 | } |
1918 | } | 1928 | } |
@@ -1943,7 +1953,7 @@ call_timeout(struct rpc_task *task) | |||
1943 | if (clnt->cl_chatty) { | 1953 | if (clnt->cl_chatty) { |
1944 | rcu_read_lock(); | 1954 | rcu_read_lock(); |
1945 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1955 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1946 | clnt->cl_protname, | 1956 | clnt->cl_program->name, |
1947 | rcu_dereference(clnt->cl_xprt)->servername); | 1957 | rcu_dereference(clnt->cl_xprt)->servername); |
1948 | rcu_read_unlock(); | 1958 | rcu_read_unlock(); |
1949 | } | 1959 | } |
@@ -1959,7 +1969,7 @@ call_timeout(struct rpc_task *task) | |||
1959 | if (clnt->cl_chatty) { | 1969 | if (clnt->cl_chatty) { |
1960 | rcu_read_lock(); | 1970 | rcu_read_lock(); |
1961 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1971 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1962 | clnt->cl_protname, | 1972 | clnt->cl_program->name, |
1963 | rcu_dereference(clnt->cl_xprt)->servername); | 1973 | rcu_dereference(clnt->cl_xprt)->servername); |
1964 | rcu_read_unlock(); | 1974 | rcu_read_unlock(); |
1965 | } | 1975 | } |
@@ -1994,7 +2004,7 @@ call_decode(struct rpc_task *task) | |||
1994 | if (clnt->cl_chatty) { | 2004 | if (clnt->cl_chatty) { |
1995 | rcu_read_lock(); | 2005 | rcu_read_lock(); |
1996 | printk(KERN_NOTICE "%s: server %s OK\n", | 2006 | printk(KERN_NOTICE "%s: server %s OK\n", |
1997 | clnt->cl_protname, | 2007 | clnt->cl_program->name, |
1998 | rcu_dereference(clnt->cl_xprt)->servername); | 2008 | rcu_dereference(clnt->cl_xprt)->servername); |
1999 | rcu_read_unlock(); | 2009 | rcu_read_unlock(); |
2000 | } | 2010 | } |
@@ -2019,7 +2029,7 @@ call_decode(struct rpc_task *task) | |||
2019 | goto out_retry; | 2029 | goto out_retry; |
2020 | } | 2030 | } |
2021 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", | 2031 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", |
2022 | clnt->cl_protname, task->tk_status); | 2032 | clnt->cl_program->name, task->tk_status); |
2023 | task->tk_action = call_timeout; | 2033 | task->tk_action = call_timeout; |
2024 | goto out_retry; | 2034 | goto out_retry; |
2025 | } | 2035 | } |
@@ -2091,7 +2101,8 @@ rpc_verify_header(struct rpc_task *task) | |||
2091 | dprintk("RPC: %5u %s: XDR representation not a multiple of" | 2101 | dprintk("RPC: %5u %s: XDR representation not a multiple of" |
2092 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, | 2102 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, |
2093 | task->tk_rqstp->rq_rcv_buf.len); | 2103 | task->tk_rqstp->rq_rcv_buf.len); |
2094 | goto out_eio; | 2104 | error = -EIO; |
2105 | goto out_err; | ||
2095 | } | 2106 | } |
2096 | if ((len -= 3) < 0) | 2107 | if ((len -= 3) < 0) |
2097 | goto out_overflow; | 2108 | goto out_overflow; |
@@ -2100,6 +2111,7 @@ rpc_verify_header(struct rpc_task *task) | |||
2100 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 2111 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
2101 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 2112 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
2102 | task->tk_pid, __func__, n); | 2113 | task->tk_pid, __func__, n); |
2114 | error = -EIO; | ||
2103 | goto out_garbage; | 2115 | goto out_garbage; |
2104 | } | 2116 | } |
2105 | 2117 | ||
@@ -2118,7 +2130,8 @@ rpc_verify_header(struct rpc_task *task) | |||
2118 | dprintk("RPC: %5u %s: RPC call rejected, " | 2130 | dprintk("RPC: %5u %s: RPC call rejected, " |
2119 | "unknown error: %x\n", | 2131 | "unknown error: %x\n", |
2120 | task->tk_pid, __func__, n); | 2132 | task->tk_pid, __func__, n); |
2121 | goto out_eio; | 2133 | error = -EIO; |
2134 | goto out_err; | ||
2122 | } | 2135 | } |
2123 | if (--len < 0) | 2136 | if (--len < 0) |
2124 | goto out_overflow; | 2137 | goto out_overflow; |
@@ -2163,9 +2176,11 @@ rpc_verify_header(struct rpc_task *task) | |||
2163 | task->tk_pid, __func__, n); | 2176 | task->tk_pid, __func__, n); |
2164 | goto out_err; | 2177 | goto out_err; |
2165 | } | 2178 | } |
2166 | if (!(p = rpcauth_checkverf(task, p))) { | 2179 | p = rpcauth_checkverf(task, p); |
2167 | dprintk("RPC: %5u %s: auth check failed\n", | 2180 | if (IS_ERR(p)) { |
2168 | task->tk_pid, __func__); | 2181 | error = PTR_ERR(p); |
2182 | dprintk("RPC: %5u %s: auth check failed with %d\n", | ||
2183 | task->tk_pid, __func__, error); | ||
2169 | goto out_garbage; /* bad verifier, retry */ | 2184 | goto out_garbage; /* bad verifier, retry */ |
2170 | } | 2185 | } |
2171 | len = p - (__be32 *)iov->iov_base - 1; | 2186 | len = p - (__be32 *)iov->iov_base - 1; |
@@ -2218,8 +2233,6 @@ out_garbage: | |||
2218 | out_retry: | 2233 | out_retry: |
2219 | return ERR_PTR(-EAGAIN); | 2234 | return ERR_PTR(-EAGAIN); |
2220 | } | 2235 | } |
2221 | out_eio: | ||
2222 | error = -EIO; | ||
2223 | out_err: | 2236 | out_err: |
2224 | rpc_exit(task, error); | 2237 | rpc_exit(task, error); |
2225 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | 2238 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, |
@@ -2291,7 +2304,7 @@ static void rpc_show_task(const struct rpc_clnt *clnt, | |||
2291 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", | 2304 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", |
2292 | task->tk_pid, task->tk_flags, task->tk_status, | 2305 | task->tk_pid, task->tk_flags, task->tk_status, |
2293 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, | 2306 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, |
2294 | clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task), | 2307 | clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task), |
2295 | task->tk_action, rpc_waitq); | 2308 | task->tk_action, rpc_waitq); |
2296 | } | 2309 | } |
2297 | 2310 | ||
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 406859cc68aa..f94567b45bb3 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -409,7 +409,7 @@ rpc_show_info(struct seq_file *m, void *v) | |||
409 | rcu_read_lock(); | 409 | rcu_read_lock(); |
410 | seq_printf(m, "RPC server: %s\n", | 410 | seq_printf(m, "RPC server: %s\n", |
411 | rcu_dereference(clnt->cl_xprt)->servername); | 411 | rcu_dereference(clnt->cl_xprt)->servername); |
412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_program->name, |
413 | clnt->cl_prog, clnt->cl_vers); | 413 | clnt->cl_prog, clnt->cl_vers); |
414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
@@ -480,23 +480,6 @@ static const struct dentry_operations rpc_dentry_operations = { | |||
480 | .d_delete = rpc_delete_dentry, | 480 | .d_delete = rpc_delete_dentry, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | /* | ||
484 | * Lookup the data. This is trivial - if the dentry didn't already | ||
485 | * exist, we know it is negative. | ||
486 | */ | ||
487 | static struct dentry * | ||
488 | rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | ||
489 | { | ||
490 | if (dentry->d_name.len > NAME_MAX) | ||
491 | return ERR_PTR(-ENAMETOOLONG); | ||
492 | d_add(dentry, NULL); | ||
493 | return NULL; | ||
494 | } | ||
495 | |||
496 | static const struct inode_operations rpc_dir_inode_operations = { | ||
497 | .lookup = rpc_lookup, | ||
498 | }; | ||
499 | |||
500 | static struct inode * | 483 | static struct inode * |
501 | rpc_get_inode(struct super_block *sb, umode_t mode) | 484 | rpc_get_inode(struct super_block *sb, umode_t mode) |
502 | { | 485 | { |
@@ -509,7 +492,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode) | |||
509 | switch (mode & S_IFMT) { | 492 | switch (mode & S_IFMT) { |
510 | case S_IFDIR: | 493 | case S_IFDIR: |
511 | inode->i_fop = &simple_dir_operations; | 494 | inode->i_fop = &simple_dir_operations; |
512 | inode->i_op = &rpc_dir_inode_operations; | 495 | inode->i_op = &simple_dir_inode_operations; |
513 | inc_nlink(inode); | 496 | inc_nlink(inode); |
514 | default: | 497 | default: |
515 | break; | 498 | break; |
@@ -901,6 +884,159 @@ rpc_unlink(struct dentry *dentry) | |||
901 | } | 884 | } |
902 | EXPORT_SYMBOL_GPL(rpc_unlink); | 885 | EXPORT_SYMBOL_GPL(rpc_unlink); |
903 | 886 | ||
887 | /** | ||
888 | * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head | ||
889 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
890 | */ | ||
891 | void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh) | ||
892 | { | ||
893 | INIT_LIST_HEAD(&pdh->pdh_entries); | ||
894 | pdh->pdh_dentry = NULL; | ||
895 | } | ||
896 | EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head); | ||
897 | |||
898 | /** | ||
899 | * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object | ||
900 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
901 | * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops | ||
902 | * @pdo_data: pointer to caller-defined data | ||
903 | */ | ||
904 | void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo, | ||
905 | const struct rpc_pipe_dir_object_ops *pdo_ops, | ||
906 | void *pdo_data) | ||
907 | { | ||
908 | INIT_LIST_HEAD(&pdo->pdo_head); | ||
909 | pdo->pdo_ops = pdo_ops; | ||
910 | pdo->pdo_data = pdo_data; | ||
911 | } | ||
912 | EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object); | ||
913 | |||
914 | static int | ||
915 | rpc_add_pipe_dir_object_locked(struct net *net, | ||
916 | struct rpc_pipe_dir_head *pdh, | ||
917 | struct rpc_pipe_dir_object *pdo) | ||
918 | { | ||
919 | int ret = 0; | ||
920 | |||
921 | if (pdh->pdh_dentry) | ||
922 | ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo); | ||
923 | if (ret == 0) | ||
924 | list_add_tail(&pdo->pdo_head, &pdh->pdh_entries); | ||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | static void | ||
929 | rpc_remove_pipe_dir_object_locked(struct net *net, | ||
930 | struct rpc_pipe_dir_head *pdh, | ||
931 | struct rpc_pipe_dir_object *pdo) | ||
932 | { | ||
933 | if (pdh->pdh_dentry) | ||
934 | pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo); | ||
935 | list_del_init(&pdo->pdo_head); | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory | ||
940 | * @net: pointer to struct net | ||
941 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
942 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
943 | * | ||
944 | */ | ||
945 | int | ||
946 | rpc_add_pipe_dir_object(struct net *net, | ||
947 | struct rpc_pipe_dir_head *pdh, | ||
948 | struct rpc_pipe_dir_object *pdo) | ||
949 | { | ||
950 | int ret = 0; | ||
951 | |||
952 | if (list_empty(&pdo->pdo_head)) { | ||
953 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
954 | |||
955 | mutex_lock(&sn->pipefs_sb_lock); | ||
956 | ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo); | ||
957 | mutex_unlock(&sn->pipefs_sb_lock); | ||
958 | } | ||
959 | return ret; | ||
960 | } | ||
961 | EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object); | ||
962 | |||
963 | /** | ||
964 | * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory | ||
965 | * @net: pointer to struct net | ||
966 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
967 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
968 | * | ||
969 | */ | ||
970 | void | ||
971 | rpc_remove_pipe_dir_object(struct net *net, | ||
972 | struct rpc_pipe_dir_head *pdh, | ||
973 | struct rpc_pipe_dir_object *pdo) | ||
974 | { | ||
975 | if (!list_empty(&pdo->pdo_head)) { | ||
976 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
977 | |||
978 | mutex_lock(&sn->pipefs_sb_lock); | ||
979 | rpc_remove_pipe_dir_object_locked(net, pdh, pdo); | ||
980 | mutex_unlock(&sn->pipefs_sb_lock); | ||
981 | } | ||
982 | } | ||
983 | EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object); | ||
984 | |||
985 | /** | ||
986 | * rpc_find_or_alloc_pipe_dir_object | ||
987 | * @net: pointer to struct net | ||
988 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
989 | * @match: match struct rpc_pipe_dir_object to data | ||
990 | * @alloc: allocate a new struct rpc_pipe_dir_object | ||
991 | * @data: user defined data for match() and alloc() | ||
992 | * | ||
993 | */ | ||
994 | struct rpc_pipe_dir_object * | ||
995 | rpc_find_or_alloc_pipe_dir_object(struct net *net, | ||
996 | struct rpc_pipe_dir_head *pdh, | ||
997 | int (*match)(struct rpc_pipe_dir_object *, void *), | ||
998 | struct rpc_pipe_dir_object *(*alloc)(void *), | ||
999 | void *data) | ||
1000 | { | ||
1001 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1002 | struct rpc_pipe_dir_object *pdo; | ||
1003 | |||
1004 | mutex_lock(&sn->pipefs_sb_lock); | ||
1005 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) { | ||
1006 | if (!match(pdo, data)) | ||
1007 | continue; | ||
1008 | goto out; | ||
1009 | } | ||
1010 | pdo = alloc(data); | ||
1011 | if (!pdo) | ||
1012 | goto out; | ||
1013 | rpc_add_pipe_dir_object_locked(net, pdh, pdo); | ||
1014 | out: | ||
1015 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1016 | return pdo; | ||
1017 | } | ||
1018 | EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object); | ||
1019 | |||
1020 | static void | ||
1021 | rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1022 | { | ||
1023 | struct rpc_pipe_dir_object *pdo; | ||
1024 | struct dentry *dir = pdh->pdh_dentry; | ||
1025 | |||
1026 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1027 | pdo->pdo_ops->create(dir, pdo); | ||
1028 | } | ||
1029 | |||
1030 | static void | ||
1031 | rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1032 | { | ||
1033 | struct rpc_pipe_dir_object *pdo; | ||
1034 | struct dentry *dir = pdh->pdh_dentry; | ||
1035 | |||
1036 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1037 | pdo->pdo_ops->destroy(dir, pdo); | ||
1038 | } | ||
1039 | |||
904 | enum { | 1040 | enum { |
905 | RPCAUTH_info, | 1041 | RPCAUTH_info, |
906 | RPCAUTH_EOF | 1042 | RPCAUTH_EOF |
@@ -941,16 +1077,29 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
941 | const char *name, | 1077 | const char *name, |
942 | struct rpc_clnt *rpc_client) | 1078 | struct rpc_clnt *rpc_client) |
943 | { | 1079 | { |
944 | return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | 1080 | struct dentry *ret; |
1081 | |||
1082 | ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | ||
945 | rpc_clntdir_populate, rpc_client); | 1083 | rpc_clntdir_populate, rpc_client); |
1084 | if (!IS_ERR(ret)) { | ||
1085 | rpc_client->cl_pipedir_objects.pdh_dentry = ret; | ||
1086 | rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1087 | } | ||
1088 | return ret; | ||
946 | } | 1089 | } |
947 | 1090 | ||
948 | /** | 1091 | /** |
949 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 1092 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
950 | * @dentry: dentry for the pipe | 1093 | * @rpc_client: rpc_client for the pipe |
951 | */ | 1094 | */ |
952 | int rpc_remove_client_dir(struct dentry *dentry) | 1095 | int rpc_remove_client_dir(struct rpc_clnt *rpc_client) |
953 | { | 1096 | { |
1097 | struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry; | ||
1098 | |||
1099 | if (dentry == NULL) | ||
1100 | return 0; | ||
1101 | rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1102 | rpc_client->cl_pipedir_objects.pdh_dentry = NULL; | ||
954 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); | 1103 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); |
955 | } | 1104 | } |
956 | 1105 | ||
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 93a7a4e94d80..ff3cc4bf4b24 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(void *word) | |||
258 | return 0; | 258 | return 0; |
259 | } | 259 | } |
260 | 260 | ||
261 | #ifdef RPC_DEBUG | 261 | #if defined(RPC_DEBUG) || defined(RPC_TRACEPOINTS) |
262 | static void rpc_task_set_debuginfo(struct rpc_task *task) | 262 | static void rpc_task_set_debuginfo(struct rpc_task *task) |
263 | { | 263 | { |
264 | static atomic_t rpc_pid; | 264 | static atomic_t rpc_pid; |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 21b75cb08c03..54530490944e 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -188,7 +188,7 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
188 | 188 | ||
189 | seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS); | 189 | seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS); |
190 | seq_printf(seq, "p/v: %u/%u (%s)\n", | 190 | seq_printf(seq, "p/v: %u/%u (%s)\n", |
191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); | 191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name); |
192 | 192 | ||
193 | rcu_read_lock(); | 193 | rcu_read_lock(); |
194 | xprt = rcu_dereference(clnt->cl_xprt); | 194 | xprt = rcu_dereference(clnt->cl_xprt); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d6656d7768f4..ee03d35677d9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <net/udp.h> | 47 | #include <net/udp.h> |
48 | #include <net/tcp.h> | 48 | #include <net/tcp.h> |
49 | 49 | ||
50 | #include <trace/events/sunrpc.h> | ||
51 | |||
50 | #include "sunrpc.h" | 52 | #include "sunrpc.h" |
51 | 53 | ||
52 | static void xs_close(struct rpc_xprt *xprt); | 54 | static void xs_close(struct rpc_xprt *xprt); |
@@ -665,8 +667,10 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) | |||
665 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 667 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
666 | struct socket *sock = transport->sock; | 668 | struct socket *sock = transport->sock; |
667 | 669 | ||
668 | if (sock != NULL) | 670 | if (sock != NULL) { |
669 | kernel_sock_shutdown(sock, SHUT_WR); | 671 | kernel_sock_shutdown(sock, SHUT_WR); |
672 | trace_rpc_socket_shutdown(xprt, sock); | ||
673 | } | ||
670 | } | 674 | } |
671 | 675 | ||
672 | /** | 676 | /** |
@@ -811,6 +815,7 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
811 | 815 | ||
812 | sk->sk_no_check = 0; | 816 | sk->sk_no_check = 0; |
813 | 817 | ||
818 | trace_rpc_socket_close(&transport->xprt, sock); | ||
814 | sock_release(sock); | 819 | sock_release(sock); |
815 | } | 820 | } |
816 | 821 | ||
@@ -1492,6 +1497,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1492 | sock_flag(sk, SOCK_ZAPPED), | 1497 | sock_flag(sk, SOCK_ZAPPED), |
1493 | sk->sk_shutdown); | 1498 | sk->sk_shutdown); |
1494 | 1499 | ||
1500 | trace_rpc_socket_state_change(xprt, sk->sk_socket); | ||
1495 | switch (sk->sk_state) { | 1501 | switch (sk->sk_state) { |
1496 | case TCP_ESTABLISHED: | 1502 | case TCP_ESTABLISHED: |
1497 | spin_lock(&xprt->transport_lock); | 1503 | spin_lock(&xprt->transport_lock); |
@@ -1896,6 +1902,7 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1896 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1902 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1897 | 1903 | ||
1898 | status = xs_local_finish_connecting(xprt, sock); | 1904 | status = xs_local_finish_connecting(xprt, sock); |
1905 | trace_rpc_socket_connect(xprt, sock, status); | ||
1899 | switch (status) { | 1906 | switch (status) { |
1900 | case 0: | 1907 | case 0: |
1901 | dprintk("RPC: xprt %p connected to %s\n", | 1908 | dprintk("RPC: xprt %p connected to %s\n", |
@@ -2039,6 +2046,7 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2039 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2046 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2040 | 2047 | ||
2041 | xs_udp_finish_connecting(xprt, sock); | 2048 | xs_udp_finish_connecting(xprt, sock); |
2049 | trace_rpc_socket_connect(xprt, sock, 0); | ||
2042 | status = 0; | 2050 | status = 0; |
2043 | out: | 2051 | out: |
2044 | xprt_clear_connecting(xprt); | 2052 | xprt_clear_connecting(xprt); |
@@ -2064,6 +2072,8 @@ static void xs_abort_connection(struct sock_xprt *transport) | |||
2064 | memset(&any, 0, sizeof(any)); | 2072 | memset(&any, 0, sizeof(any)); |
2065 | any.sa_family = AF_UNSPEC; | 2073 | any.sa_family = AF_UNSPEC; |
2066 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 2074 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
2075 | trace_rpc_socket_reset_connection(&transport->xprt, | ||
2076 | transport->sock, result); | ||
2067 | if (!result) | 2077 | if (!result) |
2068 | xs_sock_reset_connection_flags(&transport->xprt); | 2078 | xs_sock_reset_connection_flags(&transport->xprt); |
2069 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); | 2079 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); |
@@ -2194,6 +2204,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2194 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2204 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2195 | 2205 | ||
2196 | status = xs_tcp_finish_connecting(xprt, sock); | 2206 | status = xs_tcp_finish_connecting(xprt, sock); |
2207 | trace_rpc_socket_connect(xprt, sock, status); | ||
2197 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 2208 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
2198 | xprt, -status, xprt_connected(xprt), | 2209 | xprt, -status, xprt_connected(xprt), |
2199 | sock->sk->sk_state); | 2210 | sock->sk->sk_state); |