Whamcloud - gitweb
LU-6421 osc: fix bug when setting max_pages_per_rpc
[fs/lustre-release.git] / lustre / osc / lproc_osc.c
index d6e3703..73ec748 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -43,7 +43,7 @@
 #include <linux/seq_file.h>
 #include "osc_internal.h"
 
-#ifdef LPROCFS
+#ifdef CONFIG_PROC_FS
 static int osc_active_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
@@ -55,7 +55,8 @@ static int osc_active_seq_show(struct seq_file *m, void *v)
        return rc;
 }
 
-static ssize_t osc_active_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_active_seq_write(struct file *file,
+                                   const char __user *buffer,
                                    size_t count, loff_t *off)
 {
        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
@@ -83,14 +84,14 @@ static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
        struct client_obd *cli = &dev->u.cli;
        int rc;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        rc = seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        return rc;
 }
 
 static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file,
-                                               const char *buffer,
+                                               const char __user *buffer,
                                                size_t count, loff_t *off)
 {
        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
@@ -109,12 +110,13 @@ static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file,
         if (pool && val > cli->cl_max_rpcs_in_flight)
                 pool->prp_populate(pool, val-cli->cl_max_rpcs_in_flight);
 
-        client_obd_list_lock(&cli->cl_loi_list_lock);
-        cli->cl_max_rpcs_in_flight = val;
-        client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
+       cli->cl_max_rpcs_in_flight = val;
+       client_adjust_max_dirty(cli);
+       spin_unlock(&cli->cl_loi_list_lock);
 
-        LPROCFS_CLIMP_EXIT(dev);
-        return count;
+       LPROCFS_CLIMP_EXIT(dev);
+       return count;
 }
 LPROC_SEQ_FOPS(osc_max_rpcs_in_flight);
 
@@ -125,15 +127,16 @@ static int osc_max_dirty_mb_seq_show(struct seq_file *m, void *v)
         long val;
         int mult;
 
-        client_obd_list_lock(&cli->cl_loi_list_lock);
-        val = cli->cl_dirty_max;
-        client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
+       val = cli->cl_dirty_max_pages;
+       spin_unlock(&cli->cl_loi_list_lock);
 
-       mult = 1 << 20;
+       mult = 1 << (20 - PAGE_CACHE_SHIFT);
        return lprocfs_seq_read_frac_helper(m, val, mult);
 }
 
-static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_max_dirty_mb_seq_write(struct file *file,
+                                         const char __user *buffer,
                                          size_t count, loff_t *off)
 {
        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
@@ -150,10 +153,10 @@ static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer,
            pages_number > totalram_pages / 4) /* 1/4 of RAM */
                return -ERANGE;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
-       cli->cl_dirty_max = (obd_count)(pages_number << PAGE_CACHE_SHIFT);
+       spin_lock(&cli->cl_loi_list_lock);
+       cli->cl_dirty_max_pages = pages_number;
        osc_wake_cache_waiters(cli);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
 
        return count;
 }
@@ -167,34 +170,51 @@ static int osc_cached_mb_seq_show(struct seq_file *m, void *v)
        int rc;
 
        rc = seq_printf(m,
-                     "used_mb: %d\n"
-                     "busy_cnt: %d\n",
-                     (atomic_read(&cli->cl_lru_in_list) +
-                       atomic_read(&cli->cl_lru_busy)) >> shift,
-                     atomic_read(&cli->cl_lru_busy));
+                     "used_mb: %ld\n"
+                     "busy_cnt: %ld\n",
+                     (atomic_long_read(&cli->cl_lru_in_list) +
+                       atomic_long_read(&cli->cl_lru_busy)) >> shift,
+                     atomic_long_read(&cli->cl_lru_busy));
 
        return rc;
 }
 
 /* shrink the number of caching pages to a specific number */
 static ssize_t
-osc_cached_mb_seq_write(struct file *file, const char *buffer,
+osc_cached_mb_seq_write(struct file *file, const char __user *buffer,
                        size_t count, loff_t *off)
 {
        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
        struct client_obd *cli = &dev->u.cli;
-       int pages_number, mult, rc;
+       __u64 val;
+       long pages_number;
+       long rc;
+       int mult;
+       char kernbuf[128];
+
+       if (count >= sizeof(kernbuf))
+               return -EINVAL;
+
+       if (copy_from_user(kernbuf, buffer, count))
+               return -EFAULT;
+       kernbuf[count] = 0;
 
        mult = 1 << (20 - PAGE_CACHE_SHIFT);
-       buffer = lprocfs_find_named_value(buffer, "used_mb:", &count);
-       rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
+       buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) -
+                 kernbuf;
+       rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult);
+
        if (rc)
                return rc;
 
+       if (val > LONG_MAX)
+               return -ERANGE;
+       pages_number = (long)val;
+
        if (pages_number < 0)
                return -ERANGE;
 
-       rc = atomic_read(&cli->cl_lru_in_list) - pages_number;
+       rc = atomic_long_read(&cli->cl_lru_in_list) - pages_number;
        if (rc > 0) {
                struct lu_env *env;
                int refcheck;
@@ -216,9 +236,9 @@ static int osc_cur_dirty_bytes_seq_show(struct seq_file *m, void *v)
        struct client_obd *cli = &dev->u.cli;
        int rc;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%lu\n", cli->cl_dirty);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
+       rc = seq_printf(m, "%lu\n", cli->cl_dirty_pages << PAGE_CACHE_SHIFT);
+       spin_unlock(&cli->cl_loi_list_lock);
        return rc;
 }
 LPROC_SEQ_FOPS_RO(osc_cur_dirty_bytes);
@@ -229,13 +249,14 @@ static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v)
        struct client_obd *cli = &dev->u.cli;
        int rc;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        rc = seq_printf(m, "%lu\n", cli->cl_avail_grant);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        return rc;
 }
 
-static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_cur_grant_bytes_seq_write(struct file *file,
+                                            const char __user *buffer,
                                             size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -251,12 +272,13 @@ static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, const char *buff
                 return rc;
 
         /* this is only for shrinking grant */
-        client_obd_list_lock(&cli->cl_loi_list_lock);
-        if (val >= cli->cl_avail_grant) {
-                client_obd_list_unlock(&cli->cl_loi_list_lock);
-                return 0;
-        }
-        client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
+       if (val >= cli->cl_avail_grant) {
+               spin_unlock(&cli->cl_loi_list_lock);
+               return 0;
+       }
+
+       spin_unlock(&cli->cl_loi_list_lock);
 
         LPROCFS_CLIMP_CHECK(obd);
         if (cli->cl_import->imp_state == LUSTRE_IMP_FULL)
@@ -274,9 +296,9 @@ static int osc_cur_lost_grant_bytes_seq_show(struct seq_file *m, void *v)
        struct client_obd *cli = &dev->u.cli;
        int rc;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        rc = seq_printf(m, "%lu\n", cli->cl_lost_grant);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        return rc;
 }
 LPROC_SEQ_FOPS_RO(osc_cur_lost_grant_bytes);
@@ -292,7 +314,7 @@ static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v)
 }
 
 static ssize_t osc_grant_shrink_interval_seq_write(struct file *file,
-                                                  const char *buffer,
+                                                  const char __user *buffer,
                                                   size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -325,7 +347,8 @@ static int osc_checksum_seq_show(struct seq_file *m, void *v)
                          obd->u.cli.cl_checksum ? 1 : 0);
 }
 
-static ssize_t osc_checksum_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_checksum_seq_write(struct file *file,
+                                     const char __user *buffer,
                                      size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -365,7 +388,8 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static ssize_t osc_checksum_type_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_checksum_type_seq_write(struct file *file,
+                                          const char __user *buffer,
                                           size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -404,7 +428,8 @@ static int osc_resend_count_seq_show(struct seq_file *m, void *v)
        return seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends));
 }
 
-static ssize_t osc_resend_count_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_resend_count_seq_write(struct file *file,
+                                         const char __user *buffer,
                                          size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -431,7 +456,8 @@ static int osc_contention_seconds_seq_show(struct seq_file *m, void *v)
        return seq_printf(m, "%u\n", od->od_contention_time);
 }
 
-static ssize_t osc_contention_seconds_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_contention_seconds_seq_write(struct file *file,
+                                               const char __user *buffer,
                                                size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -449,7 +475,8 @@ static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v)
        return seq_printf(m, "%u\n", od->od_lockless_truncate);
 }
 
-static ssize_t osc_lockless_truncate_seq_write(struct file *file, const char *buffer,
+static ssize_t osc_lockless_truncate_seq_write(struct file *file,
+                                              const char __user *buffer,
                                    size_t count, loff_t *off)
 {
        struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
@@ -474,7 +501,7 @@ static int osc_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *v)
 }
 
 static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file,
-                                                  const char *buffer,
+                                                  const char __user *buffer,
                                                   size_t count, loff_t *off)
 {
        struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
@@ -496,13 +523,15 @@ static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file,
        chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_CACHE_SHIFT)) - 1);
        /* max_pages_per_rpc must be chunk aligned */
        val = (val + ~chunk_mask) & chunk_mask;
-       if (val == 0 || val > ocd->ocd_brw_size >> PAGE_CACHE_SHIFT) {
+       if (val == 0 || (ocd->ocd_brw_size != 0 &&
+                        val > ocd->ocd_brw_size >> PAGE_CACHE_SHIFT)) {
                LPROCFS_CLIMP_EXIT(dev);
                return -ERANGE;
        }
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        cli->cl_max_pages_per_rpc = val;
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       client_adjust_max_dirty(cli);
+       spin_unlock(&cli->cl_loi_list_lock);
 
        LPROCFS_CLIMP_EXIT(dev);
        return count;
@@ -513,13 +542,14 @@ static int osc_unstable_stats_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int pages, mb;
+       long pages;
+       int mb;
 
-       pages = atomic_read(&cli->cl_unstable_count);
+       pages = atomic_long_read(&cli->cl_unstable_count);
        mb    = (pages * PAGE_CACHE_SIZE) >> 20;
 
-       return seq_printf(m, "unstable_pages: %8d\n"
-                       "unstable_mb:    %8d\n",
+       return seq_printf(m, "unstable_pages: %20ld\n"
+                         "unstable_mb:              %10d\n",
                        pages, mb);
 }
 LPROC_SEQ_FOPS_RO(osc_unstable_stats);
@@ -542,39 +572,71 @@ LPROC_SEQ_FOPS_WO_TYPE(osc, ping);
 LPROC_SEQ_FOPS_RW_TYPE(osc, import);
 LPROC_SEQ_FOPS_RW_TYPE(osc, pinger_recov);
 
-struct lprocfs_seq_vars lprocfs_osc_obd_vars[] = {
-       { "uuid",               &osc_uuid_fops                  },
-       { "ping",               &osc_ping_fops,         0, 0222 },
-       { "connect_flags",      &osc_connect_flags_fops         },
-       { "blocksize",          &osc_blksize_fops               },
-       { "kbytestotal",        &osc_kbytestotal_fops           },
-       { "kbytesfree",         &osc_kbytesfree_fops            },
-       { "kbytesavail",        &osc_kbytesavail_fops           },
-       { "filestotal",         &osc_filestotal_fops            },
-       { "filesfree",          &osc_filesfree_fops             },
-       { "ost_server_uuid",    &osc_server_uuid_fops           },
-       { "ost_conn_uuid",      &osc_conn_uuid_fops             },
-       { "active",             &osc_active_fops                },
-       { "max_pages_per_rpc",  &osc_obd_max_pages_per_rpc_fops },
-       { "max_rpcs_in_flight", &osc_max_rpcs_in_flight_fops    },
-       { "destroys_in_flight", &osc_destroys_in_flight_fops    },
-       { "max_dirty_mb",       &osc_max_dirty_mb_fops          },
-       { "osc_cached_mb",      &osc_cached_mb_fops             },
-       { "cur_dirty_bytes",    &osc_cur_dirty_bytes_fops       },
-       { "cur_grant_bytes",    &osc_cur_grant_bytes_fops       },
-       { "cur_lost_grant_bytes",       &osc_cur_lost_grant_bytes_fops  },
-       { "grant_shrink_interval",      &osc_grant_shrink_interval_fops },
-       { "checksums",          &osc_checksum_fops              },
-       { "checksum_type",      &osc_checksum_type_fops         },
-       { "resend_count",       &osc_resend_count_fops          },
-       { "timeouts",           &osc_timeouts_fops              },
-       { "contention_seconds", &osc_contention_seconds_fops    },
-       { "lockless_truncate",  &osc_lockless_truncate_fops     },
-       { "import",             &osc_import_fops                },
-       { "state",              &osc_state_fops                 },
-       { "pinger_recov",       &osc_pinger_recov_fops          },
-       { "unstable_stats",     &osc_unstable_stats_fops        },
-       { 0 }
+struct lprocfs_vars lprocfs_osc_obd_vars[] = {
+       { .name =       "uuid",
+         .fops =       &osc_uuid_fops                  },
+       { .name =       "ping",
+         .fops =       &osc_ping_fops,
+         .proc_mode =  0222                            },
+       { .name =       "connect_flags",
+         .fops =       &osc_connect_flags_fops         },
+       { .name =       "blocksize",
+         .fops =       &osc_blksize_fops               },
+       { .name =       "kbytestotal",
+         .fops =       &osc_kbytestotal_fops           },
+       { .name =       "kbytesfree",
+         .fops =       &osc_kbytesfree_fops            },
+       { .name =       "kbytesavail",
+         .fops =       &osc_kbytesavail_fops           },
+       { .name =       "filestotal",
+         .fops =       &osc_filestotal_fops            },
+       { .name =       "filesfree",
+         .fops =       &osc_filesfree_fops             },
+       { .name =       "ost_server_uuid",
+         .fops =       &osc_server_uuid_fops           },
+       { .name =       "ost_conn_uuid",
+         .fops =       &osc_conn_uuid_fops             },
+       { .name =       "active",
+         .fops =       &osc_active_fops                },
+       { .name =       "max_pages_per_rpc",
+         .fops =       &osc_obd_max_pages_per_rpc_fops },
+       { .name =       "max_rpcs_in_flight",
+         .fops =       &osc_max_rpcs_in_flight_fops    },
+       { .name =       "destroys_in_flight",
+         .fops =       &osc_destroys_in_flight_fops    },
+       { .name =       "max_dirty_mb",
+         .fops =       &osc_max_dirty_mb_fops          },
+       { .name =       "osc_cached_mb",
+         .fops =       &osc_cached_mb_fops             },
+       { .name =       "cur_dirty_bytes",
+         .fops =       &osc_cur_dirty_bytes_fops       },
+       { .name =       "cur_grant_bytes",
+         .fops =       &osc_cur_grant_bytes_fops       },
+       { .name =       "cur_lost_grant_bytes",
+         .fops =       &osc_cur_lost_grant_bytes_fops  },
+       { .name =       "grant_shrink_interval",
+         .fops =       &osc_grant_shrink_interval_fops },
+       { .name =       "checksums",
+         .fops =       &osc_checksum_fops              },
+       { .name =       "checksum_type",
+         .fops =       &osc_checksum_type_fops         },
+       { .name =       "resend_count",
+         .fops =       &osc_resend_count_fops          },
+       { .name =       "timeouts",
+         .fops =       &osc_timeouts_fops              },
+       { .name =       "contention_seconds",
+         .fops =       &osc_contention_seconds_fops    },
+       { .name =       "lockless_truncate",
+         .fops =       &osc_lockless_truncate_fops     },
+       { .name =       "import",
+         .fops =       &osc_import_fops                },
+       { .name =       "state",
+         .fops =       &osc_state_fops                 },
+       { .name =       "pinger_recov",
+         .fops =       &osc_pinger_recov_fops          },
+       { .name =       "unstable_stats",
+         .fops =       &osc_unstable_stats_fops        },
+       { NULL }
 };
 
 #define pct(a,b) (b ? a * 100 / b : 0)
@@ -589,7 +651,7 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
 
        do_gettimeofday(&now);
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
 
        seq_printf(seq, "snapshot_time:         %lu.%lu (secs.usecs)\n",
                   now.tv_sec, now.tv_usec);
@@ -671,13 +733,14 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
                         break;
         }
 
-        client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
 
         return 0;
 }
 #undef pct
 
-static ssize_t osc_rpc_stats_seq_write(struct file *file, const char *buf,
+static ssize_t osc_rpc_stats_seq_write(struct file *file,
+                                      const char __user *buf,
                                        size_t len, loff_t *off)
 {
         struct seq_file *seq = file->private_data;
@@ -714,7 +777,8 @@ static int osc_stats_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static ssize_t osc_stats_seq_write(struct file *file, const char *buf,
+static ssize_t osc_stats_seq_write(struct file *file,
+                                  const char __user *buf,
                                    size_t len, loff_t *off)
 {
         struct seq_file *seq = file->private_data;
@@ -739,4 +803,4 @@ int lproc_osc_attach_seqstat(struct obd_device *dev)
 
        return rc;
 }
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */