diff options
author | Chuck Lever <cel@netapp.com> | 2006-03-20 13:44:14 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:14 -0500 |
commit | 91d5b47023b608227d605d1e916b29dd0215bff7 (patch) | |
tree | 31dbb285639ea68db3abc0c4129988f02d50f11a | |
parent | d9ef5a8c26aab09762afce43df64736720b4860e (diff) |
NFS: add I/O performance counters
Invoke the byte and event counter macros where we want to count bytes and
events.
Clean-up: fix a possible NULL dereference in nfs_lock, and simplify
nfs_file_open.
Test-plan:
fsx and iozone on UP and SMP systems, with and without pre-emption. Watch
for memory overwrite bugs, and performance loss (significantly more CPU
required per op).
Signed-off-by: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/dir.c | 8 | ||||
-rw-r--r-- | fs/nfs/direct.c | 7 | ||||
-rw-r--r-- | fs/nfs/file.c | 20 | ||||
-rw-r--r-- | fs/nfs/inode.c | 8 | ||||
-rw-r--r-- | fs/nfs/read.c | 12 | ||||
-rw-r--r-- | fs/nfs/write.c | 18 |
6 files changed, 62 insertions, 11 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a1554bead692..151b8dd0ac3b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include "nfs4_fs.h" | 35 | #include "nfs4_fs.h" |
36 | #include "delegation.h" | 36 | #include "delegation.h" |
37 | #include "iostat.h" | ||
37 | 38 | ||
38 | #define NFS_PARANOIA 1 | 39 | #define NFS_PARANOIA 1 |
39 | /* #define NFS_DEBUG_VERBOSE 1 */ | 40 | /* #define NFS_DEBUG_VERBOSE 1 */ |
@@ -507,6 +508,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
507 | struct nfs_fattr fattr; | 508 | struct nfs_fattr fattr; |
508 | long res; | 509 | long res; |
509 | 510 | ||
511 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); | ||
512 | |||
510 | lock_kernel(); | 513 | lock_kernel(); |
511 | 514 | ||
512 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 515 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
@@ -713,6 +716,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
713 | parent = dget_parent(dentry); | 716 | parent = dget_parent(dentry); |
714 | lock_kernel(); | 717 | lock_kernel(); |
715 | dir = parent->d_inode; | 718 | dir = parent->d_inode; |
719 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); | ||
716 | inode = dentry->d_inode; | 720 | inode = dentry->d_inode; |
717 | 721 | ||
718 | if (!inode) { | 722 | if (!inode) { |
@@ -844,6 +848,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
844 | 848 | ||
845 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 849 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
846 | dentry->d_parent->d_name.name, dentry->d_name.name); | 850 | dentry->d_parent->d_name.name, dentry->d_name.name); |
851 | nfs_inc_stats(dir, NFSIOS_VFSLOOKUP); | ||
847 | 852 | ||
848 | res = ERR_PTR(-ENAMETOOLONG); | 853 | res = ERR_PTR(-ENAMETOOLONG); |
849 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) | 854 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
@@ -1241,6 +1246,7 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
1241 | dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", | 1246 | dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", |
1242 | dentry->d_parent->d_name.name, dentry->d_name.name, | 1247 | dentry->d_parent->d_name.name, dentry->d_name.name, |
1243 | atomic_read(&dentry->d_count)); | 1248 | atomic_read(&dentry->d_count)); |
1249 | nfs_inc_stats(dir, NFSIOS_SILLYRENAME); | ||
1244 | 1250 | ||
1245 | #ifdef NFS_PARANOIA | 1251 | #ifdef NFS_PARANOIA |
1246 | if (!dentry->d_inode) | 1252 | if (!dentry->d_inode) |
@@ -1640,6 +1646,8 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
1640 | struct rpc_cred *cred; | 1646 | struct rpc_cred *cred; |
1641 | int res = 0; | 1647 | int res = 0; |
1642 | 1648 | ||
1649 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); | ||
1650 | |||
1643 | if (mask == 0) | 1651 | if (mask == 0) |
1644 | goto out; | 1652 | goto out; |
1645 | /* Is this sys_access() ? */ | 1653 | /* Is this sys_access() ? */ |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 4e9b3a1b36c5..fc07ce4885da 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -54,6 +54,8 @@ | |||
54 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
55 | #include <asm/atomic.h> | 55 | #include <asm/atomic.h> |
56 | 56 | ||
57 | #include "iostat.h" | ||
58 | |||
57 | #define NFSDBG_FACILITY NFSDBG_VFS | 59 | #define NFSDBG_FACILITY NFSDBG_VFS |
58 | #define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT) | 60 | #define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT) |
59 | 61 | ||
@@ -67,6 +69,7 @@ struct nfs_direct_req { | |||
67 | struct kref kref; /* release manager */ | 69 | struct kref kref; /* release manager */ |
68 | struct list_head list; /* nfs_read_data structs */ | 70 | struct list_head list; /* nfs_read_data structs */ |
69 | wait_queue_head_t wait; /* wait for i/o completion */ | 71 | wait_queue_head_t wait; /* wait for i/o completion */ |
72 | struct inode * inode; /* target file of I/O */ | ||
70 | struct page ** pages; /* pages in our buffer */ | 73 | struct page ** pages; /* pages in our buffer */ |
71 | unsigned int npages; /* count of pages */ | 74 | unsigned int npages; /* count of pages */ |
72 | atomic_t complete, /* i/os we're waiting for */ | 75 | atomic_t complete, /* i/os we're waiting for */ |
@@ -357,7 +360,9 @@ static ssize_t nfs_direct_read_seg(struct inode *inode, | |||
357 | 360 | ||
358 | dreq->pages = pages; | 361 | dreq->pages = pages; |
359 | dreq->npages = nr_pages; | 362 | dreq->npages = nr_pages; |
363 | dreq->inode = inode; | ||
360 | 364 | ||
365 | nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count); | ||
361 | rpc_clnt_sigmask(clnt, &oldset); | 366 | rpc_clnt_sigmask(clnt, &oldset); |
362 | nfs_direct_read_schedule(dreq, inode, ctx, user_addr, count, | 367 | nfs_direct_read_schedule(dreq, inode, ctx, user_addr, count, |
363 | file_offset); | 368 | file_offset); |
@@ -572,6 +577,7 @@ static ssize_t nfs_direct_write(struct inode *inode, | |||
572 | return page_count; | 577 | return page_count; |
573 | } | 578 | } |
574 | 579 | ||
580 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, size); | ||
575 | result = nfs_direct_write_seg(inode, ctx, user_addr, size, | 581 | result = nfs_direct_write_seg(inode, ctx, user_addr, size, |
576 | file_offset, pages, page_count); | 582 | file_offset, pages, page_count); |
577 | nfs_free_user_pages(pages, page_count, 0); | 583 | nfs_free_user_pages(pages, page_count, 0); |
@@ -581,6 +587,7 @@ static ssize_t nfs_direct_write(struct inode *inode, | |||
581 | break; | 587 | break; |
582 | return result; | 588 | return result; |
583 | } | 589 | } |
590 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result); | ||
584 | tot_bytes += result; | 591 | tot_bytes += result; |
585 | file_offset += result; | 592 | file_offset += result; |
586 | if (result < size) | 593 | if (result < size) |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 387809f2d188..1cf07e4ad136 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
33 | 33 | ||
34 | #include "delegation.h" | 34 | #include "delegation.h" |
35 | #include "iostat.h" | ||
35 | 36 | ||
36 | #define NFSDBG_FACILITY NFSDBG_FILE | 37 | #define NFSDBG_FACILITY NFSDBG_FILE |
37 | 38 | ||
@@ -102,18 +103,15 @@ static int nfs_check_flags(int flags) | |||
102 | static int | 103 | static int |
103 | nfs_file_open(struct inode *inode, struct file *filp) | 104 | nfs_file_open(struct inode *inode, struct file *filp) |
104 | { | 105 | { |
105 | struct nfs_server *server = NFS_SERVER(inode); | ||
106 | int (*open)(struct inode *, struct file *); | ||
107 | int res; | 106 | int res; |
108 | 107 | ||
109 | res = nfs_check_flags(filp->f_flags); | 108 | res = nfs_check_flags(filp->f_flags); |
110 | if (res) | 109 | if (res) |
111 | return res; | 110 | return res; |
112 | 111 | ||
112 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); | ||
113 | lock_kernel(); | 113 | lock_kernel(); |
114 | /* Do NFSv4 open() call */ | 114 | res = NFS_SERVER(inode)->rpc_ops->file_open(inode, filp); |
115 | if ((open = server->rpc_ops->file_open) != NULL) | ||
116 | res = open(inode, filp); | ||
117 | unlock_kernel(); | 115 | unlock_kernel(); |
118 | return res; | 116 | return res; |
119 | } | 117 | } |
@@ -124,6 +122,7 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
124 | /* Ensure that dirty pages are flushed out with the right creds */ | 122 | /* Ensure that dirty pages are flushed out with the right creds */ |
125 | if (filp->f_mode & FMODE_WRITE) | 123 | if (filp->f_mode & FMODE_WRITE) |
126 | filemap_fdatawrite(filp->f_mapping); | 124 | filemap_fdatawrite(filp->f_mapping); |
125 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); | ||
127 | return NFS_PROTO(inode)->file_release(inode, filp); | 126 | return NFS_PROTO(inode)->file_release(inode, filp); |
128 | } | 127 | } |
129 | 128 | ||
@@ -199,6 +198,7 @@ nfs_file_flush(struct file *file) | |||
199 | 198 | ||
200 | if ((file->f_mode & FMODE_WRITE) == 0) | 199 | if ((file->f_mode & FMODE_WRITE) == 0) |
201 | return 0; | 200 | return 0; |
201 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | ||
202 | lock_kernel(); | 202 | lock_kernel(); |
203 | /* Ensure that data+attribute caches are up to date after close() */ | 203 | /* Ensure that data+attribute caches are up to date after close() */ |
204 | status = nfs_wb_all(inode); | 204 | status = nfs_wb_all(inode); |
@@ -229,6 +229,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos) | |||
229 | (unsigned long) count, (unsigned long) pos); | 229 | (unsigned long) count, (unsigned long) pos); |
230 | 230 | ||
231 | result = nfs_revalidate_file(inode, iocb->ki_filp); | 231 | result = nfs_revalidate_file(inode, iocb->ki_filp); |
232 | nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count); | ||
232 | if (!result) | 233 | if (!result) |
233 | result = generic_file_aio_read(iocb, buf, count, pos); | 234 | result = generic_file_aio_read(iocb, buf, count, pos); |
234 | return result; | 235 | return result; |
@@ -282,6 +283,7 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
282 | 283 | ||
283 | dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); | 284 | dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); |
284 | 285 | ||
286 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | ||
285 | lock_kernel(); | 287 | lock_kernel(); |
286 | status = nfs_wb_all(inode); | 288 | status = nfs_wb_all(inode); |
287 | if (!status) { | 289 | if (!status) { |
@@ -378,6 +380,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t | |||
378 | if (!count) | 380 | if (!count) |
379 | goto out; | 381 | goto out; |
380 | 382 | ||
383 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | ||
381 | result = generic_file_aio_write(iocb, buf, count, pos); | 384 | result = generic_file_aio_write(iocb, buf, count, pos); |
382 | out: | 385 | out: |
383 | return result; | 386 | return result; |
@@ -517,9 +520,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
517 | inode->i_sb->s_id, inode->i_ino, | 520 | inode->i_sb->s_id, inode->i_ino, |
518 | fl->fl_type, fl->fl_flags, | 521 | fl->fl_type, fl->fl_flags, |
519 | (long long)fl->fl_start, (long long)fl->fl_end); | 522 | (long long)fl->fl_start, (long long)fl->fl_end); |
520 | 523 | nfs_inc_stats(inode, NFSIOS_VFSLOCK); | |
521 | if (!inode) | ||
522 | return -EINVAL; | ||
523 | 524 | ||
524 | /* No mandatory locks over NFS */ | 525 | /* No mandatory locks over NFS */ |
525 | if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && | 526 | if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && |
@@ -544,9 +545,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
544 | inode->i_sb->s_id, inode->i_ino, | 545 | inode->i_sb->s_id, inode->i_ino, |
545 | fl->fl_type, fl->fl_flags); | 546 | fl->fl_type, fl->fl_flags); |
546 | 547 | ||
547 | if (!inode) | ||
548 | return -EINVAL; | ||
549 | |||
550 | /* | 548 | /* |
551 | * No BSD flocks over NFS allowed. | 549 | * No BSD flocks over NFS allowed. |
552 | * Note: we could try to fake a POSIX lock request here by | 550 | * Note: we could try to fake a POSIX lock request here by |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 86b756f44e27..8ee74111e519 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -753,6 +753,8 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
753 | struct nfs_inode *nfsi = NFS_I(inode); | 753 | struct nfs_inode *nfsi = NFS_I(inode); |
754 | int mode = inode->i_mode; | 754 | int mode = inode->i_mode; |
755 | 755 | ||
756 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | ||
757 | |||
756 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 758 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); |
757 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 759 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; |
758 | 760 | ||
@@ -940,6 +942,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
940 | struct nfs_fattr fattr; | 942 | struct nfs_fattr fattr; |
941 | int error; | 943 | int error; |
942 | 944 | ||
945 | nfs_inc_stats(inode, NFSIOS_VFSSETATTR); | ||
946 | |||
943 | if (attr->ia_valid & ATTR_SIZE) { | 947 | if (attr->ia_valid & ATTR_SIZE) { |
944 | if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode)) | 948 | if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode)) |
945 | attr->ia_valid &= ~ATTR_SIZE; | 949 | attr->ia_valid &= ~ATTR_SIZE; |
@@ -993,6 +997,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
993 | spin_unlock(&inode->i_lock); | 997 | spin_unlock(&inode->i_lock); |
994 | } | 998 | } |
995 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 999 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
1000 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | ||
996 | inode->i_size = attr->ia_size; | 1001 | inode->i_size = attr->ia_size; |
997 | vmtruncate(inode, attr->ia_size); | 1002 | vmtruncate(inode, attr->ia_size); |
998 | } | 1003 | } |
@@ -1278,6 +1283,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
1278 | */ | 1283 | */ |
1279 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 1284 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
1280 | { | 1285 | { |
1286 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | ||
1281 | if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) | 1287 | if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) |
1282 | && !nfs_attribute_timeout(inode)) | 1288 | && !nfs_attribute_timeout(inode)) |
1283 | return NFS_STALE(inode) ? -ESTALE : 0; | 1289 | return NFS_STALE(inode) ? -ESTALE : 0; |
@@ -1294,6 +1300,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1294 | struct nfs_inode *nfsi = NFS_I(inode); | 1300 | struct nfs_inode *nfsi = NFS_I(inode); |
1295 | 1301 | ||
1296 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { | 1302 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
1303 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | ||
1297 | if (S_ISREG(inode->i_mode)) | 1304 | if (S_ISREG(inode->i_mode)) |
1298 | nfs_sync_mapping(mapping); | 1305 | nfs_sync_mapping(mapping); |
1299 | invalidate_inode_pages2(mapping); | 1306 | invalidate_inode_pages2(mapping); |
@@ -1615,6 +1622,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1615 | 1622 | ||
1616 | /* Update attrtimeo value if we're out of the unstable period */ | 1623 | /* Update attrtimeo value if we're out of the unstable period */ |
1617 | if (invalid & NFS_INO_INVALID_ATTR) { | 1624 | if (invalid & NFS_INO_INVALID_ATTR) { |
1625 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | ||
1618 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1626 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1619 | nfsi->attrtimeo_timestamp = jiffies; | 1627 | nfsi->attrtimeo_timestamp = jiffies; |
1620 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1628 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 05eb43fadf8e..ae3ddd24cf8f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
33 | 33 | ||
34 | #include "iostat.h" | ||
35 | |||
34 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 36 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
35 | 37 | ||
36 | static int nfs_pagein_one(struct list_head *, struct inode *); | 38 | static int nfs_pagein_one(struct list_head *, struct inode *); |
@@ -133,6 +135,8 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
133 | } | 135 | } |
134 | count -= result; | 136 | count -= result; |
135 | rdata->args.pgbase += result; | 137 | rdata->args.pgbase += result; |
138 | nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, result); | ||
139 | |||
136 | /* Note: result == 0 should only happen if we're caching | 140 | /* Note: result == 0 should only happen if we're caching |
137 | * a write that extends the file and punches a hole. | 141 | * a write that extends the file and punches a hole. |
138 | */ | 142 | */ |
@@ -458,8 +462,11 @@ void nfs_readpage_result(struct rpc_task *task, void *calldata) | |||
458 | dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", | 462 | dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", |
459 | task->tk_pid, status); | 463 | task->tk_pid, status); |
460 | 464 | ||
465 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); | ||
466 | |||
461 | /* Is this a short read? */ | 467 | /* Is this a short read? */ |
462 | if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { | 468 | if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { |
469 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); | ||
463 | /* Has the server at least made some progress? */ | 470 | /* Has the server at least made some progress? */ |
464 | if (resp->count != 0) { | 471 | if (resp->count != 0) { |
465 | /* Yes, so retry the read at the end of the data */ | 472 | /* Yes, so retry the read at the end of the data */ |
@@ -491,6 +498,9 @@ int nfs_readpage(struct file *file, struct page *page) | |||
491 | 498 | ||
492 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", | 499 | dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", |
493 | page, PAGE_CACHE_SIZE, page->index); | 500 | page, PAGE_CACHE_SIZE, page->index); |
501 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); | ||
502 | nfs_add_stats(inode, NFSIOS_READPAGES, 1); | ||
503 | |||
494 | /* | 504 | /* |
495 | * Try to flush any pending writes to the file.. | 505 | * Try to flush any pending writes to the file.. |
496 | * | 506 | * |
@@ -570,6 +580,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
570 | inode->i_sb->s_id, | 580 | inode->i_sb->s_id, |
571 | (long long)NFS_FILEID(inode), | 581 | (long long)NFS_FILEID(inode), |
572 | nr_pages); | 582 | nr_pages); |
583 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); | ||
573 | 584 | ||
574 | if (filp == NULL) { | 585 | if (filp == NULL) { |
575 | desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); | 586 | desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); |
@@ -582,6 +593,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
582 | if (!list_empty(&head)) { | 593 | if (!list_empty(&head)) { |
583 | int err = nfs_pagein_list(&head, server->rpages); | 594 | int err = nfs_pagein_list(&head, server->rpages); |
584 | if (!ret) | 595 | if (!ret) |
596 | nfs_add_stats(inode, NFSIOS_READPAGES, err); | ||
585 | ret = err; | 597 | ret = err; |
586 | } | 598 | } |
587 | put_nfs_open_context(desc.ctx); | 599 | put_nfs_open_context(desc.ctx); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 92ecf24455c3..e7c8361cf201 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/smp_lock.h> | 63 | #include <linux/smp_lock.h> |
64 | 64 | ||
65 | #include "delegation.h" | 65 | #include "delegation.h" |
66 | #include "iostat.h" | ||
66 | 67 | ||
67 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 68 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
68 | 69 | ||
@@ -134,6 +135,7 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c | |||
134 | end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); | 135 | end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); |
135 | if (i_size >= end) | 136 | if (i_size >= end) |
136 | return; | 137 | return; |
138 | nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); | ||
137 | i_size_write(inode, end); | 139 | i_size_write(inode, end); |
138 | } | 140 | } |
139 | 141 | ||
@@ -223,6 +225,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
223 | wdata->args.pgbase += result; | 225 | wdata->args.pgbase += result; |
224 | written += result; | 226 | written += result; |
225 | count -= result; | 227 | count -= result; |
228 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result); | ||
226 | } while (count); | 229 | } while (count); |
227 | /* Update file length */ | 230 | /* Update file length */ |
228 | nfs_grow_file(page, offset, written); | 231 | nfs_grow_file(page, offset, written); |
@@ -279,6 +282,9 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) | |||
279 | int priority = wb_priority(wbc); | 282 | int priority = wb_priority(wbc); |
280 | int err; | 283 | int err; |
281 | 284 | ||
285 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | ||
286 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | ||
287 | |||
282 | /* | 288 | /* |
283 | * Note: We need to ensure that we have a reference to the inode | 289 | * Note: We need to ensure that we have a reference to the inode |
284 | * if we are to do asynchronous writes. If not, waiting | 290 | * if we are to do asynchronous writes. If not, waiting |
@@ -343,6 +349,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
343 | struct inode *inode = mapping->host; | 349 | struct inode *inode = mapping->host; |
344 | int err; | 350 | int err; |
345 | 351 | ||
352 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | ||
353 | |||
346 | err = generic_writepages(mapping, wbc); | 354 | err = generic_writepages(mapping, wbc); |
347 | if (err) | 355 | if (err) |
348 | return err; | 356 | return err; |
@@ -354,6 +362,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
354 | err = nfs_flush_inode(inode, 0, 0, wb_priority(wbc)); | 362 | err = nfs_flush_inode(inode, 0, 0, wb_priority(wbc)); |
355 | if (err < 0) | 363 | if (err < 0) |
356 | goto out; | 364 | goto out; |
365 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, err); | ||
357 | wbc->nr_to_write -= err; | 366 | wbc->nr_to_write -= err; |
358 | if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) { | 367 | if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) { |
359 | err = nfs_wait_on_requests(inode, 0, 0); | 368 | err = nfs_wait_on_requests(inode, 0, 0); |
@@ -596,6 +605,9 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) | |||
596 | 605 | ||
597 | if (!bdi_write_congested(bdi)) | 606 | if (!bdi_write_congested(bdi)) |
598 | return 0; | 607 | return 0; |
608 | |||
609 | nfs_inc_stats(mapping->host, NFSIOS_CONGESTIONWAIT); | ||
610 | |||
599 | if (intr) { | 611 | if (intr) { |
600 | struct rpc_clnt *clnt = NFS_CLIENT(mapping->host); | 612 | struct rpc_clnt *clnt = NFS_CLIENT(mapping->host); |
601 | sigset_t oldset; | 613 | sigset_t oldset; |
@@ -749,6 +761,8 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
749 | struct nfs_page *req; | 761 | struct nfs_page *req; |
750 | int status = 0; | 762 | int status = 0; |
751 | 763 | ||
764 | nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); | ||
765 | |||
752 | dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", | 766 | dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", |
753 | file->f_dentry->d_parent->d_name.name, | 767 | file->f_dentry->d_parent->d_name.name, |
754 | file->f_dentry->d_name.name, count, | 768 | file->f_dentry->d_name.name, count, |
@@ -1152,6 +1166,8 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata) | |||
1152 | dprintk("NFS: %4d nfs_writeback_done (status %d)\n", | 1166 | dprintk("NFS: %4d nfs_writeback_done (status %d)\n", |
1153 | task->tk_pid, task->tk_status); | 1167 | task->tk_pid, task->tk_status); |
1154 | 1168 | ||
1169 | nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); | ||
1170 | |||
1155 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1171 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1156 | if (resp->verf->committed < argp->stable && task->tk_status >= 0) { | 1172 | if (resp->verf->committed < argp->stable && task->tk_status >= 0) { |
1157 | /* We tried a write call, but the server did not | 1173 | /* We tried a write call, but the server did not |
@@ -1177,6 +1193,8 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata) | |||
1177 | if (task->tk_status >= 0 && resp->count < argp->count) { | 1193 | if (task->tk_status >= 0 && resp->count < argp->count) { |
1178 | static unsigned long complain; | 1194 | static unsigned long complain; |
1179 | 1195 | ||
1196 | nfs_inc_stats(data->inode, NFSIOS_SHORTWRITE); | ||
1197 | |||
1180 | /* Has the server at least made some progress? */ | 1198 | /* Has the server at least made some progress? */ |
1181 | if (resp->count != 0) { | 1199 | if (resp->count != 0) { |
1182 | /* Was this an NFSv2 write or an NFSv3 stable write? */ | 1200 | /* Was this an NFSv2 write or an NFSv3 stable write? */ |