*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
int lprocfs_wr_uint(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
- unsigned *p = data;
- char dummy[MAX_STRING_SIZE + 1], *end;
- unsigned long tmp;
+ unsigned *p = data;
+ char dummy[MAX_STRING_SIZE + 1];
+ char *end;
+ unsigned long tmp;
- dummy[MAX_STRING_SIZE] = '\0';
- if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
- return -EFAULT;
+ if (count >= sizeof(dummy))
+ return -EINVAL;
- tmp = simple_strtoul(dummy, &end, 0);
- if (dummy == end)
- return -EINVAL;
+ if (count == 0)
+ return 0;
+
+ if (copy_from_user(dummy, buffer, count))
+ return -EFAULT;
- *p = (unsigned int)tmp;
- return count;
+ dummy[count] = 0;
+
+ tmp = simple_strtoul(dummy, &end, 0);
+ if (dummy == end)
+ return -EINVAL;
+
+ *p = (unsigned int)tmp;
+ return count;
}
EXPORT_SYMBOL(lprocfs_wr_uint);
int lprocfs_u64_seq_show(struct seq_file *m, void *data)
{
LASSERT(data != NULL);
- seq_printf(m, LPU64"\n", *(__u64 *)data);
+ seq_printf(m, "%llu\n", *(__u64 *)data);
return 0;
}
EXPORT_SYMBOL(lprocfs_u64_seq_show);
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
OBD_STATFS_NODELAY);
if (!rc)
- seq_printf(m, LPU64"\n", osfs.os_files);
+ seq_printf(m, "%llu\n", osfs.os_files);
return rc;
}
EXPORT_SYMBOL(lprocfs_filestotal_seq_show);
cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
OBD_STATFS_NODELAY);
if (!rc)
- seq_printf(m, LPU64"\n", osfs.os_ffree);
+ seq_printf(m, "%llu\n", osfs.os_ffree);
return rc;
}
EXPORT_SYMBOL(lprocfs_filesfree_seq_show);
EXPORT_SYMBOL(lprocfs_conn_uuid_seq_show);
/** add up per-cpu counters */
+
+/**
+ * Lock statistics structure for access, possibly only on this CPU.
+ *
+ * The statistics struct may be allocated with per-CPU structures for
+ * efficient concurrent update (usually only on server-wide stats), or
+ * as a single global struct (e.g. for per-client or per-job statistics),
+ * so the required locking depends on the type of structure allocated.
+ *
+ * For per-CPU statistics, pin the thread to the current cpuid so that
+ * will only access the statistics for that CPU. If the stats structure
+ * for the current CPU has not been allocated (or previously freed),
+ * allocate it now. The per-CPU statistics do not need locking since
+ * the thread is pinned to the CPU during update.
+ *
+ * For global statistics, lock the stats structure to prevent concurrent update.
+ *
+ * \param[in] stats statistics structure to lock
+ * \param[in] opc type of operation:
+ * LPROCFS_GET_SMP_ID: "lock" and return current CPU index
+ * for incrementing statistics for that CPU
+ * LPROCFS_GET_NUM_CPU: "lock" and return number of used
+ * CPU indices to iterate over all indices
+ * \param[out] flags CPU interrupt saved state for IRQ-safe locking
+ *
+ * \retval cpuid of current thread or number of allocated structs
+ * \retval negative on error (only for opc LPROCFS_GET_SMP_ID + per-CPU stats)
+ */
+int lprocfs_stats_lock(struct lprocfs_stats *stats,
+ enum lprocfs_stats_lock_ops opc,
+ unsigned long *flags)
+{
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
+ spin_lock_irqsave(&stats->ls_lock, *flags);
+ else
+ spin_lock(&stats->ls_lock);
+ return opc == LPROCFS_GET_NUM_CPU ? 1 : 0;
+ }
+
+ switch (opc) {
+ case LPROCFS_GET_SMP_ID: {
+ unsigned int cpuid = get_cpu();
+
+ if (unlikely(!stats->ls_percpu[cpuid])) {
+ int rc = lprocfs_stats_alloc_one(stats, cpuid);
+
+ if (rc < 0) {
+ put_cpu();
+ return rc;
+ }
+ }
+ return cpuid;
+ }
+ case LPROCFS_GET_NUM_CPU:
+ return stats->ls_biggest_alloc_num;
+ default:
+ LBUG();
+ }
+}
+
+/**
+ * Unlock statistics structure after access.
+ *
+ * Unlock the lock acquired via lprocfs_stats_lock() for global statistics,
+ * or unpin this thread from the current cpuid for per-CPU statistics.
+ *
+ * This function must be called using the same arguments as used when calling
+ * lprocfs_stats_lock() so that the correct operation can be performed.
+ *
+ * \param[in] stats statistics structure to unlock
+ * \param[in] opc type of operation (current cpuid or number of structs)
+ * \param[in] flags CPU interrupt saved state for IRQ-safe locking
+ */
+void lprocfs_stats_unlock(struct lprocfs_stats *stats,
+ enum lprocfs_stats_lock_ops opc,
+ unsigned long *flags)
+{
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
+ spin_unlock_irqrestore(&stats->ls_lock, *flags);
+ else
+ spin_unlock(&stats->ls_lock);
+ } else if (opc == LPROCFS_GET_SMP_ID) {
+ put_cpu();
+ }
+}
+
+/** add up per-cpu counters */
void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
struct lprocfs_counter *cnt)
{
#undef flag2str
static const char *obd_connect_names[] = {
+ /* flags names */
"read_only",
"lov_index",
"connect_from_mds",
"bulk_mbits",
"compact_obdo",
"second_flags",
+ /* flags2 names */
+ "file_secctx",
NULL
};
-static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
+static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags,
+ __u64 flags2, const char *sep)
{
bool first = true;
- __u64 mask = 1;
+ __u64 mask;
int i;
- for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
+ for (i = 0, mask = 1; i < 64; i++, mask <<= 1) {
if (flags & mask) {
seq_printf(m, "%s%s",
first ? "" : sep, obd_connect_names[i]);
first = false;
}
}
- if (flags & ~(mask - 1))
- seq_printf(m, "%sunknown_"LPX64,
+
+ if (flags & ~(mask - 1)) {
+ seq_printf(m, "%sunknown_%#llx",
first ? "" : sep, flags & ~(mask - 1));
+ first = false;
+ }
+
+ if (!(flags & OBD_CONNECT_FLAGS2) || flags2 == 0)
+ return;
+
+ for (i = 64, mask = 1; obd_connect_names[i] != NULL; i++, mask <<= 1) {
+ if (flags2 & mask) {
+ seq_printf(m, "%s%s",
+ first ? "" : sep, obd_connect_names[i]);
+ first = false;
+ }
+ }
+
+ if (flags2 & ~(mask - 1)) {
+ seq_printf(m, "%sunknown2_%#llx",
+ first ? "" : sep, flags2 & ~(mask - 1));
+ first = false;
+ }
}
-int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
+int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2,
+ const char *sep)
{
- __u64 mask = 1;
+ __u64 mask;
int i, ret = 0;
- for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
+ for (i = 0, mask = 1; i < 64; i++, mask <<= 1) {
if (flags & mask)
ret += snprintf(page + ret, count - ret, "%s%s",
ret ? sep : "", obd_connect_names[i]);
}
+
if (flags & ~(mask - 1))
ret += snprintf(page + ret, count - ret,
- "%sunknown_"LPX64,
+ "%sunknown_%#llx",
ret ? sep : "", flags & ~(mask - 1));
+
+ if (!(flags & OBD_CONNECT_FLAGS2) || flags2 == 0)
+ return ret;
+
+ for (i = 64, mask = 1; obd_connect_names[i] != NULL; i++, mask <<= 1) {
+ if (flags2 & mask)
+ ret += snprintf(page + ret, count - ret, "%s%s",
+ ret ? sep : "", obd_connect_names[i]);
+ }
+
+ if (flags2 & ~(mask - 1))
+ ret += snprintf(page + ret, count - ret,
+ "%sunknown2_%#llx",
+ ret ? sep : "", flags2 & ~(mask - 1));
+
return ret;
}
EXPORT_SYMBOL(obd_connect_flags2str);
flags = ocd->ocd_connect_flags;
seq_printf(m, " connect_data:\n"
- " flags: "LPX64"\n"
+ " flags: %#llx\n"
" instance: %u\n",
ocd->ocd_connect_flags,
ocd->ocd_instance);
if (flags & OBD_CONNECT_BRW_SIZE)
seq_printf(m, " max_brw_size: %d\n", ocd->ocd_brw_size);
if (flags & OBD_CONNECT_IBITS)
- seq_printf(m, " ibits_known: "LPX64"\n",
+ seq_printf(m, " ibits_known: %#llx\n",
ocd->ocd_ibits_known);
if (flags & OBD_CONNECT_GRANT_PARAM)
seq_printf(m, " grant_block_size: %d\n"
ocd->ocd_grant_max_blks << ocd->ocd_grant_blkbits,
ocd->ocd_grant_tax_kb << 10);
if (flags & OBD_CONNECT_TRANSNO)
- seq_printf(m, " first_transno: "LPX64"\n",
+ seq_printf(m, " first_transno: %#llx\n",
ocd->ocd_transno);
if (flags & OBD_CONNECT_CKSUM)
seq_printf(m, " cksum_types: %#x\n",
if (flags & OBD_CONNECT_MAX_EASIZE)
seq_printf(m, " max_easize: %d\n", ocd->ocd_max_easize);
if (flags & OBD_CONNECT_MAXBYTES)
- seq_printf(m, " max_object_bytes: "LPU64"\n",
+ seq_printf(m, " max_object_bytes: %llu\n",
ocd->ocd_maxbytes);
if (flags & OBD_CONNECT_MULTIMODRPCS)
seq_printf(m, " max_mod_rpcs: %hu\n",
obd2cli_tgt(obd),
ptlrpc_import_state_name(imp->imp_state));
obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
+ imp->imp_connect_data.ocd_connect_flags2,
", ");
seq_printf(m, " ]\n");
obd_connect_data_seqprint(m, ocd);
" inflight: %u\n"
" unregistering: %u\n"
" timeouts: %u\n"
- " avg_waittime: "LPU64" %s\n",
+ " avg_waittime: %llu %s\n",
atomic_read(&imp->imp_inflight),
atomic_read(&imp->imp_unregistering),
atomic_read(&imp->imp_timeouts),
at_get(&imp->imp_at.iat_net_latency));
seq_printf(m, " transactions:\n"
- " last_replay: "LPU64"\n"
- " peer_committed: "LPU64"\n"
- " last_checked: "LPU64"\n",
+ " last_replay: %llu\n"
+ " peer_committed: %llu\n"
+ " last_checked: %llu\n",
imp->imp_last_replay_transno,
imp->imp_peer_committed_transno,
imp->imp_last_transno_checked);
do_div(sum, ret.lc_count);
ret.lc_sum = sum;
seq_printf(m, " %s_data_averages:\n"
- " bytes_per_rpc: "LPU64"\n",
+ " bytes_per_rpc: %llu\n",
rw ? "write" : "read",
ret.lc_sum);
}
__u64 sum = ret.lc_sum;
do_div(sum, ret.lc_count);
ret.lc_sum = sum;
- seq_printf(m, " %s_per_rpc: "LPU64"\n",
+ seq_printf(m, " %s_per_rpc: %llu\n",
header->lc_units, ret.lc_sum);
j = (int)ret.lc_sum;
if (j > 0)
{
struct obd_device *obd = data;
__u64 flags;
+ __u64 flags2;
LPROCFS_CLIMP_CHECK(obd);
flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
- seq_printf(m, "flags="LPX64"\n", flags);
- obd_connect_seq_flags2str(m, flags, "\n");
+ flags2 = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags2;
+ seq_printf(m, "flags=%#llx\n", flags);
+ seq_printf(m, "flags2=%#llx\n", flags2);
+ obd_connect_seq_flags2str(m, flags, flags2, "\n");
seq_printf(m, "\n");
LPROCFS_CLIMP_EXIT(obd);
return 0;
}
return rc;
}
-EXPORT_SYMBOL(lprocfs_stats_alloc_one);
struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
enum lprocfs_stats_flags flags)
}
EXPORT_SYMBOL(lprocfs_free_stats);
+u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx,
+ enum lprocfs_fields_flags field)
+{
+ unsigned long flags = 0;
+ unsigned int num_cpu;
+ unsigned int i;
+ u64 ret = 0;
+
+ LASSERT(stats);
+
+ num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
+ for (i = 0; i < num_cpu; i++) {
+ struct lprocfs_counter *cntr;
+
+ if (!stats->ls_percpu[i])
+ continue;
+
+ cntr = lprocfs_stats_counter_get(stats, i, idx);
+ ret += lprocfs_read_helper(cntr, &stats->ls_cnt_header[idx],
+ stats->ls_flags, field);
+ }
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
+ return ret;
+}
+EXPORT_SYMBOL(lprocfs_stats_collector);
+
void lprocfs_clear_stats(struct lprocfs_stats *stats)
{
struct lprocfs_counter *percpu_cntr;
struct lprocfs_counter_header *hdr;
struct lprocfs_counter ctr;
int idx = *(loff_t *)v;
- int rc = 0;
if (idx == 0) {
struct timeval now;
do_gettimeofday(&now);
seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
"snapshot_time", now.tv_sec, now.tv_usec);
- if (rc < 0)
- return rc;
}
hdr = &stats->ls_cnt_header[idx];
lprocfs_stats_collect(stats, idx, &ctr);
if (ctr.lc_count == 0)
- goto out;
+ return 0;
- seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
+ seq_printf(p, "%-25s %lld samples [%s]", hdr->lc_name,
ctr.lc_count, hdr->lc_units);
- if (rc < 0)
- goto out;
if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
- seq_printf(p, " "LPD64" "LPD64" "LPD64,
+ seq_printf(p, " %lld %lld %lld",
ctr.lc_min, ctr.lc_max, ctr.lc_sum);
- if (rc < 0)
- goto out;
if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
- seq_printf(p, " "LPD64, ctr.lc_sumsquare);
- if (rc < 0)
- goto out;
+ seq_printf(p, " %llu", ctr.lc_sumsquare);
}
seq_putc(p, '\n');
-out:
- return (rc < 0) ? rc : 0;
+ return 0;
}
static const struct seq_operations lprocfs_stats_seq_sops = {
void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
{
- LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
+ LPROCFS_MD_OP_INIT(num_private_stats, stats, get_root);
LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
- LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
}
start = buffer;
while (*buffer) {
+ /* allow for a single new line before the null terminator */
+ if (*buffer == '\n') {
+ *buffer = '\0';
+ buffer++;
+
+ if (*buffer)
+ return -EINVAL;
+
+ break;
+ }
+
/* any chars after our unit indicates a malformed string */
if (hit_unit)
return -EINVAL;
int lprocfs_str_with_units_to_s64(const char __user *buffer,
unsigned long count, __s64 *val, char defunit)
{
- __u64 mult;
+ __u64 mult = 1;
int rc;
- rc = get_mult(defunit, &mult);
- if (rc)
- return rc;
+ if (defunit != '1') {
+ rc = get_mult(defunit, &mult);
+ if (rc)
+ return rc;
+ }
return str_to_s64_internal(buffer, count, val, mult, true);
}