* Use is subject to license terms.
*/
/*
+ * Copyright (c) 2011 Whamcloud, Inc.
+ */
+/*
* This file is part of Lustre, http://www.lustre.org/
* Lustre is a trademark of Sun Microsystems, Inc.
*
{
struct proc_dir_entry *temp;
- LPROCFS_ENTRY();
+ LPROCFS_SRCH_ENTRY();
temp = __lprocfs_srch(head, name);
- LPROCFS_EXIT();
+ LPROCFS_SRCH_EXIT();
return temp;
}
"0x%p %s/%s len %d\n", rm_entry, temp->name,
rm_entry->name, (int)strlen(rm_entry->name));
+#ifdef HAVE_PROCFS_USERS
+ /* if procfs uses user count to synchronize deletion of
+ * proc entry, there is no protection for rm_entry->data,
+ * then lprocfs_fops_read and lprocfs_fops_write maybe
+ * call proc_dir_entry->read_proc (or write_proc) with
+ * proc_dir_entry->data == NULL, then cause kernel Oops.
+ * see bug19706 for detailed information */
+
+ /* procfs won't free rm_entry->data if it isn't a LINK,
+ * and Lustre won't use rm_entry->data if it is a LINK */
+ if (S_ISLNK(rm_entry->mode))
+ rm_entry->data = NULL;
+#else
/* Now, the rm_entry->deleted flags is protected
* by _lprocfs_lock. */
rm_entry->data = NULL;
+#endif
remove_proc_entry(rm_entry->name, temp);
if (temp == parent)
break;
cnt->lc_min = LC_MIN_INIT;
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
- num_cpu = 1;
- else
- num_cpu = cfs_num_possible_cpus();
+ num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
for (i = 0; i < num_cpu; i++) {
percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
}
cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
}
/**
"large_ea",
"full20",
"layout_lock",
+ "64bithash",
+ "object_max_bytes",
NULL
};
-static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
+int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
{
__u64 mask = 1;
int i, ret = 0;
ret ? sep : "", flags & ~(mask - 1));
return ret;
}
+EXPORT_SYMBOL(obd_connect_flags2str);
int lprocfs_rd_import(char *page, char **start, off_t off, int count,
int *eof, void *data)
client_stat->nid_brw_stats);
LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
- "count %d\n",
- cfs_atomic_read(&client_stat->nid_exp_ref_count));
+ "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
+ atomic_read(&client_stat->nid_exp_ref_count));
cfs_hlist_del_init(&client_stat->nid_hash);
}
}
- lprocfs_stats_unlock(stats);
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
}
static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
c->lc_units = units;
}
- lprocfs_stats_unlock(stats);
+ lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
}
EXPORT_SYMBOL(lprocfs_counter_init);
}
EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
-int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
- int *newnid)
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
{
struct nid_stat *new_stat, *old_stat;
struct obd_device *obd = NULL;
old_stat, libcfs_nid2str(*nid),
cfs_atomic_read(&new_stat->nid_exp_ref_count));
+ /* We need to release old stats because lprocfs_exp_cleanup() hasn't
+ * been and will never be called. */
+ if (exp->exp_nid_stats) {
+ nidstat_putref(exp->exp_nid_stats);
+ exp->exp_nid_stats = NULL;
+ }
+
/* Return -EALREADY here so that we know that the /proc
* entry already has been created */
if (old_stat != new_stat) {
- /* if this connects to the existing export of same nid,
- * we need to release old stats for obd_disconnect won't
- * balance the reference gotten in "cfs_hash_findadd_uinque" */
- if (reconnect && exp->exp_nid_stats)
- nidstat_putref(old_stat);
-
exp->exp_nid_stats = old_stat;
GOTO(destroy_new, rc = -EALREADY);
}
}
EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
+int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ struct obd_device *dev = data;
+ struct client_obd *cli = &dev->u.cli;
+ int rc;
+
+ client_obd_list_lock(&cli->cl_loi_list_lock);
+ rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
+ client_obd_list_unlock(&cli->cl_loi_list_lock);
+ return rc;
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
+
+int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ struct obd_device *dev = data;
+ struct client_obd *cli = &dev->u.cli;
+ struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
+ int val, rc;
+
+ rc = lprocfs_write_helper(buffer, count, &val);
+ if (rc)
+ return rc;
+
+ LPROCFS_CLIMP_CHECK(dev);
+ if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) {
+ LPROCFS_CLIMP_EXIT(dev);
+ return -ERANGE;
+ }
+ client_obd_list_lock(&cli->cl_loi_list_lock);
+ cli->cl_max_pages_per_rpc = val;
+ client_obd_list_unlock(&cli->cl_loi_list_lock);
+
+ LPROCFS_CLIMP_EXIT(dev);
+ return count;
+}
+EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc);
+
EXPORT_SYMBOL(lprocfs_register);
EXPORT_SYMBOL(lprocfs_srch);
EXPORT_SYMBOL(lprocfs_remove);