/* safe snprintf */
int cfs_snprintf(char *buf, size_t size, const char *fmt, ...);
+
+/* trim leading and trailing space characters */
+char *cfs_firststr(char *str, size_t size);
#endif
return i;
}
EXPORT_SYMBOL(cfs_snprintf);
+
+/* get the first string out of @str */
+char *cfs_firststr(char *str, size_t size)
+{
+ size_t i = 0;
+ char *end;
+
+ /* trim leading spaces */
+ while (i < size && *str && isspace(*str)) {
+ ++i;
+ ++str;
+ }
+
+ /* string with all spaces */
+ if (*str == '\0')
+ goto out;
+
+ end = str;
+ while (i < size && *end != '\0' && !isspace(*end)) {
+ ++i;
+ ++end;
+ }
+
+ *end= '\0';
+out:
+ return str;
+}
+EXPORT_SYMBOL(cfs_firststr);
return count;
}
+#define BUFLEN (UUID_MAX + 4)
+
static int lprocfs_mds_wr_evict_client(struct file *file, const char *buffer,
unsigned long count, void *data)
{
- struct obd_device *obd = data;
- struct mds_obd *mds = &obd->u.mds;
- char tmpbuf[sizeof(struct obd_uuid)];
struct ptlrpc_request_set *set;
- int rc;
+ struct obd_device *obd = data;
+ struct mds_obd *mds = &obd->u.mds;
+ char *kbuf;
+ char *tmpbuf;
+ int rc;
+
+ OBD_ALLOC(kbuf, BUFLEN);
+ if (kbuf == NULL)
+ return -ENOMEM;
- sscanf(buffer, "%40s", tmpbuf);
+ /*
+ * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
+ * bytes into kbuf, to ensure that the string is NUL-terminated.
+ * UUID_MAX should include a trailing NUL already.
+ */
+ if (cfs_copy_from_user(kbuf, buffer,
+ min_t(unsigned long, BUFLEN - 1, count))) {
+ count = -EFAULT;
+ goto out;
+ }
+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
- if (strncmp(tmpbuf, "nid:", 4) != 0)
- return lprocfs_wr_evict_client(file, buffer, count, data);
+ if (strncmp(tmpbuf, "nid:", 4) != 0) {
+ count = lprocfs_wr_evict_client(file, buffer, count, data);
+ goto out;
+ }
set = ptlrpc_prep_set();
- if (!set)
- return -ENOMEM;
+ if (set == NULL) {
+ count = -ENOMEM;
+ goto out;
+ }
if (obd->u.mds.mds_evict_ost_nids) {
rc = obd_set_info_async(mds->mds_lov_exp,
class_incref(obd, __FUNCTION__, cfs_current());
LPROCFS_EXIT();
- obd_export_evict_by_nid(obd, tmpbuf+4);
+ obd_export_evict_by_nid(obd, tmpbuf + 4);
rc = ptlrpc_set_wait(set);
class_decref(obd, __FUNCTION__, cfs_current());
ptlrpc_set_destroy(set);
+out:
+ OBD_FREE(kbuf, BUFLEN);
return count;
}
+#undef BUFLEN
+
static int lprocfs_wr_atime_diff(struct file *file, const char *buffer,
unsigned long count, void *data)
{
return count;
}
+#define BUFLEN (UUID_MAX + 4)
+
static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
unsigned long count, void *data)
{
- char tmpbuf[sizeof(struct obd_uuid)];
+ char *kbuf;
+ char *tmpbuf;
- sscanf(buffer, "%40s", tmpbuf);
+ OBD_ALLOC(kbuf, BUFLEN);
+ if (kbuf == NULL)
+ return -ENOMEM;
- if (strncmp(tmpbuf, "nid:", 4) != 0)
- return lprocfs_wr_evict_client(file, buffer, count, data);
+ /*
+ * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
+ * bytes into kbuf, to ensure that the string is NUL-terminated.
+ * UUID_MAX should include a trailing NUL already.
+ */
+ if (cfs_copy_from_user(kbuf, buffer,
+ min_t(unsigned long, BUFLEN - 1, count))) {
+ count = -EFAULT;
+ goto out;
+ }
+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
+
+ if (strncmp(tmpbuf, "nid:", 4) != 0) {
+ count = lprocfs_wr_evict_client(file, buffer, count, data);
+ goto out;
+ }
CERROR("NOT implement evict client by nid %s\n", tmpbuf);
+out:
+ OBD_FREE(kbuf, BUFLEN);
return count;
}
+#undef BUFLEN
+
static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
{
struct obd_device *obd = data;
struct obd_export *exp = NULL;
- struct obd_uuid uuid;
- char tmpbuf[sizeof(struct obd_uuid)];
+ struct obd_uuid *uuid;
+ char *kbuf;
+ char *tmpbuf;
- sscanf(buffer, "%40s", tmpbuf);
+ OBD_ALLOC(kbuf, UUID_MAX);
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ /*
+ * OBD_ALLOC() will zero kbuf, but we only copy UUID_MAX - 1
+ * bytes into kbuf, to ensure that the string is NUL-terminated.
+ * UUID_MAX should include a trailing NUL already.
+ */
+ if (cfs_copy_from_user(kbuf, buffer,
+ min_t(unsigned long, UUID_MAX - 1, count))) {
+ count = -EFAULT;
+ goto out;
+ }
+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, UUID_MAX - 1, count));
- obd_str2uuid(&uuid, tmpbuf);
- exp = cfs_hash_lookup(obd->obd_uuid_hash, &uuid);
+ OBD_ALLOC(uuid, UUID_MAX);
+ if (uuid == NULL) {
+ count = -ENOMEM;
+ goto out;
+ }
+
+ obd_str2uuid(uuid, tmpbuf);
+ exp = cfs_hash_lookup(obd->obd_uuid_hash, uuid);
if (exp == NULL) {
CERROR("%s: no export %s found\n",
- obd->obd_name, obd_uuid2str(&uuid));
+ obd->obd_name, obd_uuid2str(uuid));
} else {
mdt_hsm_copytool_send(exp);
class_export_put(exp);
}
+ OBD_FREE(uuid, UUID_MAX);
+out:
+ OBD_FREE(kbuf, UUID_MAX);
return count;
}
EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd);
+#define BUFLEN (UUID_MAX + 5)
+
int lprocfs_wr_evict_client(struct file *file, const char *buffer,
unsigned long count, void *data)
{
struct obd_device *obd = data;
- char tmpbuf[sizeof(struct obd_uuid)];
+ char *kbuf;
+ char *tmpbuf;
+
+ OBD_ALLOC(kbuf, BUFLEN);
+ if (kbuf == NULL)
+ return -ENOMEM;
+ /*
+ * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
+ * bytes into kbuf, to ensure that the string is NUL-terminated.
+ * UUID_MAX should include a trailing NUL already.
+ */
+ if (cfs_copy_from_user(kbuf, buffer,
+ min_t(unsigned long, BUFLEN - 1, count))) {
+ count = -EFAULT;
+ goto out;
+ }
+ tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
/* Kludge code(deadlock situation): the lprocfs lock has been held
* since the client is evicted by writting client's
* uuid/nid to procfs "evict_client" entry. However,
class_incref(obd, __FUNCTION__, cfs_current());
LPROCFS_EXIT();
- sscanf(buffer, "%40s", tmpbuf);
if (strncmp(tmpbuf, "nid:", 4) == 0)
obd_export_evict_by_nid(obd, tmpbuf + 4);
else if (strncmp(tmpbuf, "uuid:", 5) == 0)
LPROCFS_ENTRY();
class_decref(obd, __FUNCTION__, cfs_current());
+out:
+ OBD_FREE(kbuf, BUFLEN);
return count;
}
EXPORT_SYMBOL(lprocfs_wr_evict_client);
+#undef BUFLEN
+
int lprocfs_wr_ping(struct file *file, const char *buffer,
unsigned long count, void *data)
{