Initial patches commit

This commit is contained in:
Mario Fetka 2012-11-24 17:08:51 +01:00
commit a902c236c9
148 changed files with 455965 additions and 0 deletions

View File

@ -0,0 +1,553 @@
From dc13dec93dbd04bfa7a9ba67df1b8ed3431d8d48 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:39 -0700
Subject: [PATCH 1/3] AppArmor: compatibility patch for v5 network controll
Add compatibility for v5 network rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
include/linux/lsm_audit.h | 4 +
security/apparmor/Makefile | 19 ++++-
security/apparmor/include/net.h | 40 +++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 48 ++++++++++-
8 files changed, 394 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 88e78de..c63979a 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -124,6 +124,10 @@ struct common_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
} apparmor_audit_data;
#endif
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50..7cefef9 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o
+ resource.o sid.o file.o net.o
-clean-files := capability_names.h rlim_names.h
+clean-files := capability_names.h rlim_names.h af_names.h
# Build a lower case string table of capability names
@@ -44,9 +44,24 @@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
echo "};" >> $@
+# Build a lower case string table of address family names.
+# Transform lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [2] = "inet",
+quiet_cmd_make-af = GEN $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
+ sed $< >> $@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+).*/[\2] = "\L\1",/p';\
+ echo "};" >> $@
+
+
$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
+$(obj)/net.o : $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
$(call cmd,make-rlim)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
\ No newline at end of file
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..3c7d599
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+ u16 allow[AF_MAX];
+ u16 audit[AF_MAX];
+ u16 quiet[AF_MAX];
+};
+
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
+ int type, int protocol, struct sock *sk);
+extern int aa_revalidate_sk(int op, struct sock *sk);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+ /* NOP */
+}
+
+#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index aeda5cf..6776929 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -27,6 +27,7 @@
#include "capability.h"
#include "domain.h"
#include "file.h"
+#include "net.h"
#include "resource.h"
extern const char *profile_mode_names[];
@@ -145,6 +146,7 @@ struct aa_namespace {
* @size: the memory consumed by this profiles rules
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
+ * @net: network controls for the profile
* @rlimits: rlimits for the profile
*
* The AppArmor profile contains the basic confinement data. Each profile
@@ -181,6 +183,7 @@ struct aa_profile {
struct aa_file_rules file;
struct aa_caps caps;
+ struct aa_net net;
struct aa_rlimit rlimits;
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 3d2fd14..aa293ae 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -32,6 +32,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
+#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
@@ -621,6 +622,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
return error;
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
+ NULL);
+ return error;
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_BIND, sk);
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_CONNECT, sk);
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_LISTEN, sk);
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_ACCEPT, sk);
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SENDMSG, sk);
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_RECVMSG, sk);
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -652,6 +751,19 @@ static struct security_operations apparmor_ops = {
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .socket_create = apparmor_socket_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
+
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 0000000..1765901
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,170 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "af_names.h"
+
+static const char *sock_type_names[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ audit_log_format(ab, " family=");
+ if (address_family_names[sa->u.net.family]) {
+ audit_log_string(ab, address_family_names[sa->u.net.family]);
+ } else {
+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
+ }
+
+ audit_log_format(ab, " sock_type=");
+ if (sock_type_names[sa->aad.net.type]) {
+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
+ }
+
+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
+}
+
+/**
+ * audit_net - audit network access
+ * @profile: profile being enforced (NOT NULL)
+ * @op: operation being checked
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ * @sk: socket auditing is being applied to
+ * @error: error code for failure else 0
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+ int protocol, struct sock *sk, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa;
+ if (sk) {
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
+ } else {
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ }
+ /* todo fill in socket addr info */
+
+ sa.aad.op = op,
+ sa.u.net.family = family;
+ sa.u.net.sk = sk;
+ sa.aad.net.type = type;
+ sa.aad.net.protocol = protocol;
+ sa.aad.error = error;
+
+ if (likely(!sa.aad.error)) {
+ u16 audit_mask = profile->net.audit[sa.u.net.family];
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+ !(1 << sa.aad.net.type & audit_mask)))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
+ u16 kill_mask = 0;
+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
+
+ if (denied & kill_mask)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ if ((denied & quiet_mask) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+ }
+
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @op: operation being checked
+ * @profile: profile being enforced (NOT NULL)
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
+ int protocol, struct sock *sk)
+{
+ u16 family_mask;
+ int error;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->net.allow[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ return audit_net(profile, op, family, type, protocol, sk, error);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @op: operation being checked
+ * @sk: sock being revalidated (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(int op, struct sock *sk)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* aa_revalidate_sk should not be called from interrupt context
+ * don't mediate these calls as they are not task related
+ */
+ if (in_interrupt())
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
+ sk->sk_protocol, sk);
+
+ return error;
+}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 4f0eade..4d5ce13 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
aa_free_file_rules(&profile->file);
aa_free_cap_rules(&profile->caps);
+ aa_free_net_rules(&profile->net);
aa_free_rlimit_rules(&profile->rlimits);
aa_free_sid(profile->sid);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index d6d9a57..f4874c4 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -190,6 +190,19 @@ fail:
return 0;
}
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+ if (unpack_nameX(e, AA_U16, name)) {
+ if (!inbounds(e, sizeof(u16)))
+ return 0;
+ if (data)
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+ e->pos += sizeof(u16);
+ return 1;
+ }
+ return 0;
+}
+
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
if (unpack_nameX(e, AA_U32, name)) {
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
if (!unpack_rlimits(e, profile))
goto fail;
+ size = unpack_array(e, "net_allowed_af");
+ if (size) {
+
+ for (i = 0; i < size; i++) {
+ /* discard extraneous rules that this kernel will
+ * never request
+ */
+ if (i >= AF_MAX) {
+ u16 tmp;
+ if (!unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL))
+ goto fail;
+ continue;
+ }
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ /*
+ * allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ }
+ profile->net.allow[AF_UNIX] = 0xffff;
+ profile->net.allow[AF_NETLINK] = 0xffff;
+
/* get file rules */
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {
--
1.7.5.4

View File

@ -0,0 +1,299 @@
From f9072731bedac6f6373dd75798b5a801ce614c02 Mon Sep 17 00:00:00 2001
From: Arianna Avanzini <avanzini.arianna@gmail.com>
Date: Mon, 19 Dec 2011 16:33:41 +0100
Subject: [PATCH 1/3] block: prepare I/O context code for BFQ-v5 for 3.2
BFQ uses struct cfq_io_context to store its per-process per-device data,
reusing the same code for cic handling of CFQ. The code is not shared
ATM to minimize the impact of these patches.
This patch introduces a new hlist to each io_context to store all the
cic's allocated by BFQ to allow calling the right destructor on module
unload; the radix tree used for cic lookup needs to be duplicated
because it can contain dead keys inserted by a scheduler and later
retrieved by the other one.
Update the io_context exit and free paths to take care also of
the BFQ cic's.
Change the type of cfqq inside struct cfq_io_context to void *
to use it also for BFQ per-queue data.
A new bfq-specific ioprio_changed field is necessary, too, to avoid
clobbering cfq's one, so switch ioprio_changed to a bitmap, with one
element per scheduler.
Signed-off-by: Fabio Checconi <fabio@gandalf.sssup.it>
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
---
block/Kconfig.iosched | 26 ++++++++++++++++++++++++++
block/blk-ioc.c | 30 +++++++++++++++++-------------
block/cfq-iosched.c | 10 +++++++---
fs/ioprio.c | 9 +++++++--
include/linux/iocontext.h | 18 +++++++++++++++---
5 files changed, 72 insertions(+), 21 deletions(-)
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 3199b76..5905452 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -43,6 +43,28 @@ config CFQ_GROUP_IOSCHED
---help---
Enable group IO scheduling in CFQ.
+config IOSCHED_BFQ
+ tristate "BFQ I/O scheduler"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ The BFQ I/O scheduler tries to distribute bandwidth among
+ all processes according to their weights.
+ It aims at distributing the bandwidth as desired, independently of
+ the disk parameters and with any workload. It also tries to
+ guarantee low latency to interactive and soft real-time
+ applications. If compiled built-in (saying Y here), BFQ can
+ be configured to support hierarchical scheduling.
+
+config CGROUP_BFQIO
+ bool "BFQ hierarchical scheduling support"
+ depends on CGROUPS && IOSCHED_BFQ=y
+ default n
+ ---help---
+ Enable hierarchical scheduling in BFQ, using the cgroups
+ filesystem interface. The name of the subsystem will be
+ bfqio.
+
choice
prompt "Default I/O scheduler"
default DEFAULT_CFQ
@@ -56,6 +78,9 @@ choice
config DEFAULT_CFQ
bool "CFQ" if IOSCHED_CFQ=y
+ config DEFAULT_BFQ
+ bool "BFQ" if IOSCHED_BFQ=y
+
config DEFAULT_NOOP
bool "No-op"
@@ -65,6 +90,7 @@ config DEFAULT_IOSCHED
string
default "deadline" if DEFAULT_DEADLINE
default "cfq" if DEFAULT_CFQ
+ default "bfq" if DEFAULT_BFQ
default "noop" if DEFAULT_NOOP
endmenu
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 6f9bbd9..d0d16d4 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
+#include <linux/bitmap.h>
#include <linux/blkdev.h>
#include <linux/bootmem.h> /* for max_pfn/max_low_pfn */
#include <linux/slab.h>
@@ -16,13 +17,12 @@
*/
static struct kmem_cache *iocontext_cachep;
-static void cfq_dtor(struct io_context *ioc)
+static void hlist_sched_dtor(struct io_context *ioc, struct hlist_head *list)
{
- if (!hlist_empty(&ioc->cic_list)) {
+ if (!hlist_empty(list)) {
struct cfq_io_context *cic;
- cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,
- cic_list);
+ cic = hlist_entry(list->first, struct cfq_io_context, cic_list);
cic->dtor(ioc);
}
}
@@ -40,7 +40,9 @@ int put_io_context(struct io_context *ioc)
if (atomic_long_dec_and_test(&ioc->refcount)) {
rcu_read_lock();
- cfq_dtor(ioc);
+
+ hlist_sched_dtor(ioc, &ioc->cic_list);
+ hlist_sched_dtor(ioc, &ioc->bfq_cic_list);
rcu_read_unlock();
kmem_cache_free(iocontext_cachep, ioc);
@@ -50,15 +52,14 @@ int put_io_context(struct io_context *ioc)
}
EXPORT_SYMBOL(put_io_context);
-static void cfq_exit(struct io_context *ioc)
+static void hlist_sched_exit(struct io_context *ioc, struct hlist_head *list)
{
rcu_read_lock();
- if (!hlist_empty(&ioc->cic_list)) {
+ if (!hlist_empty(list)) {
struct cfq_io_context *cic;
- cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,
- cic_list);
+ cic = hlist_entry(list->first, struct cfq_io_context, cic_list);
cic->exit(ioc);
}
rcu_read_unlock();
@@ -74,9 +75,10 @@ void exit_io_context(struct task_struct *task)
task->io_context = NULL;
task_unlock(task);
- if (atomic_dec_and_test(&ioc->nr_tasks))
- cfq_exit(ioc);
-
+ if (atomic_dec_and_test(&ioc->nr_tasks)) {
+ hlist_sched_exit(ioc, &ioc->cic_list);
+ hlist_sched_exit(ioc, &ioc->bfq_cic_list);
+ }
put_io_context(ioc);
}
@@ -89,12 +91,14 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
atomic_long_set(&ioc->refcount, 1);
atomic_set(&ioc->nr_tasks, 1);
spin_lock_init(&ioc->lock);
- ioc->ioprio_changed = 0;
+ bitmap_zero(ioc->ioprio_changed, IOC_IOPRIO_CHANGED_BITS);
ioc->ioprio = 0;
ioc->last_waited = 0; /* doesn't matter... */
ioc->nr_batch_requests = 0; /* because this is 0 */
INIT_RADIX_TREE(&ioc->radix_root, GFP_ATOMIC | __GFP_HIGH);
INIT_HLIST_HEAD(&ioc->cic_list);
+ INIT_RADIX_TREE(&ioc->bfq_radix_root, GFP_ATOMIC | __GFP_HIGH);
+ INIT_HLIST_HEAD(&ioc->bfq_cic_list);
ioc->ioc_data = NULL;
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
ioc->cgroup_changed = 0;
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 3548705..a120a31 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2946,7 +2946,6 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
static void cfq_ioc_set_ioprio(struct io_context *ioc)
{
call_for_each_cic(ioc, changed_ioprio);
- ioc->ioprio_changed = 0;
}
static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
@@ -3238,8 +3237,13 @@ retry:
goto err_free;
out:
- smp_read_barrier_depends();
- if (unlikely(ioc->ioprio_changed))
+ /*
+ * test_and_clear_bit() implies a memory barrier, paired with
+ * the wmb() in fs/ioprio.c, so the value seen for ioprio is the
+ * new one.
+ */
+ if (unlikely(test_and_clear_bit(IOC_CFQ_IOPRIO_CHANGED,
+ ioc->ioprio_changed)))
cfq_ioc_set_ioprio(ioc);
#ifdef CONFIG_CFQ_GROUP_IOSCHED
diff --git a/fs/ioprio.c b/fs/ioprio.c
index f79dab8..6b0cb885 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -31,7 +31,7 @@
int set_task_ioprio(struct task_struct *task, int ioprio)
{
- int err;
+ int err, i;
struct io_context *ioc;
const struct cred *cred = current_cred(), *tcred;
@@ -61,12 +61,17 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
err = -ENOMEM;
break;
}
+ /* let other ioc users see the new values */
+ smp_wmb();
task->io_context = ioc;
} while (1);
if (!err) {
ioc->ioprio = ioprio;
- ioc->ioprio_changed = 1;
+ /* make sure schedulers see the new ioprio value */
+ wmb();
+ for (i = 0; i < IOC_IOPRIO_CHANGED_BITS; i++)
+ set_bit(i, ioc->ioprio_changed);
}
task_unlock(task);
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 5037a0a..69fdd58 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -1,10 +1,10 @@
#ifndef IOCONTEXT_H
#define IOCONTEXT_H
+#include <linux/bitmap.h>
#include <linux/radix-tree.h>
#include <linux/rcupdate.h>
-struct cfq_queue;
struct cfq_ttime {
unsigned long last_end_request;
@@ -16,7 +16,7 @@ struct cfq_ttime {
struct cfq_io_context {
void *key;
- struct cfq_queue *cfqq[2];
+ void *cfqq[2];
struct io_context *ioc;
@@ -32,6 +32,16 @@ struct cfq_io_context {
};
/*
+ * Indexes into the ioprio_changed bitmap. A bit set indicates that
+ * the corresponding I/O scheduler needs to see a ioprio update.
+ */
+enum {
+ IOC_CFQ_IOPRIO_CHANGED,
+ IOC_BFQ_IOPRIO_CHANGED,
+ IOC_IOPRIO_CHANGED_BITS
+};
+
+/*
* I/O subsystem state of the associated processes. It is refcounted
* and kmalloc'ed. These could be shared between processes.
*/
@@ -43,7 +53,7 @@ struct io_context {
spinlock_t lock;
unsigned short ioprio;
- unsigned short ioprio_changed;
+ DECLARE_BITMAP(ioprio_changed, IOC_IOPRIO_CHANGED_BITS);
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
unsigned short cgroup_changed;
@@ -57,6 +67,8 @@ struct io_context {
struct radix_tree_root radix_root;
struct hlist_head cic_list;
+ struct radix_tree_root bfq_radix_root;
+ struct hlist_head bfq_cic_list;
void __rcu *ioc_data;
};
--
1.7.10.4

View File

@ -0,0 +1,391 @@
From a2515f25ad5a7833ddc5a032d34eee6a5ddee3a2 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:40 -0700
Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 1 +
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 18 ++-
security/apparmor/include/apparmorfs.h | 6 +
5 files changed, 319 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/apparmorfs-24.c
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b..51ebf96 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
boot.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+ bool "Enable AppArmor 2.4 compatability"
+ depends on SECURITY_APPARMOR
+ default y
+ help
+ This option enables compatability with AppArmor 2.4. It is
+ recommended if compatability with older versions of AppArmor
+ is desired.
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 7cefef9..0bb604b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o sid.o file.o net.o
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
clean-files := capability_names.h rlim_names.h af_names.h
diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
new file mode 100644
index 0000000..dc8c744
--- /dev/null
+++ b/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,287 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+ "user::other";
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+ .read = aa_features_read,
+};
+
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ struct aa_namespace *parent;
+
+ /* is next namespace a child */
+ if (!list_empty(&ns->sub_ns)) {
+ struct aa_namespace *next;
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+ read_lock(&next->lock);
+ return next;
+ }
+
+ /* check if the next ns is a sibling, parent, gp, .. */
+ parent = ns->parent;
+ while (parent) {
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+ read_lock(&ns->lock);
+ return ns;
+ }
+ if (parent == root)
+ return NULL;
+ ns = parent;
+ parent = parent->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+static struct aa_profile *__first_profile(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ for ( ; ns; ns = __next_namespace(root, ns)) {
+ if (!list_empty(&ns->base.profiles))
+ return list_first_entry(&ns->base.profiles,
+ struct aa_profile, base.list);
+ }
+ return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+ struct aa_profile *parent;
+ struct aa_namespace *ns = p->ns;
+
+ /* is next profile a child */
+ if (!list_empty(&p->base.profiles))
+ return list_first_entry(&p->base.profiles, typeof(*p),
+ base.list);
+
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
+ parent = p->parent;
+ while (parent) {
+ list_for_each_entry_continue(p, &parent->base.profiles,
+ base.list)
+ return p;
+ p = parent;
+ parent = parent->parent;
+ }
+
+ /* is next another profile in the namespace */
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace (NOT NULL)
+ * @profile: current profile (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+ struct aa_profile *profile)
+{
+ struct aa_profile *next = __next_profile(profile);
+ if (next)
+ return next;
+
+ /* finished all profiles in namespace move to next namespace */
+ return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+ __acquires(root->lock)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *root = aa_current_profile()->ns;
+ loff_t l = *pos;
+ f->private = aa_get_namespace(root);
+
+
+ /* find the first profile */
+ read_lock(&root->lock);
+ profile = __first_profile(root, root);
+
+ /* skip to position */
+ for (; profile && l > 0; l--)
+ profile = next_profile(root, profile);
+
+ return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private;
+ (*pos)++;
+
+ return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+ __releases(root->lock)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private, *ns;
+
+ if (profile) {
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+ read_unlock(&ns->lock);
+ }
+ read_unlock(&root->lock);
+ aa_put_namespace(root);
+}
+
+/**
+ * seq_show_profile - show a profile entry
+ * @f: seq_file to file
+ * @p: current position (profile) (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_namespace *root = f->private;
+
+ if (profile->ns != root)
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+ return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
+
+static int profiles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int profiles_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+const struct file_operations aa_fs_profiles_fops = {
+ .open = profiles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = profiles_release,
+};
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 0848292..28c52ac 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
aafs_remove(".remove");
aafs_remove(".replace");
aafs_remove(".load");
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ aafs_remove("profiles");
+ aafs_remove("matching");
+ aafs_remove("features");
+#endif
securityfs_remove(aa_fs_dentry);
aa_fs_dentry = NULL;
}
@@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
aa_fs_dentry = NULL;
goto error;
}
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+ if (error)
+ goto error;
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
+ if (error)
+ goto error;
+#endif
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a..14f955c 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,4 +17,10 @@
extern void __init aa_destroy_aafs(void);
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+extern const struct file_operations aa_fs_profiles_fops;
+#endif
+
#endif /* __AA_APPARMORFS_H */
--
1.7.5.4

View File

@ -0,0 +1,46 @@
From 9396d61706a827dfc4dcdfdc8f687e0e9e24f53d Mon Sep 17 00:00:00 2001
From: Arianna Avanzini <avanzini.arianna@gmail.com>
Date: Mon, 19 Dec 2011 16:34:01 +0100
Subject: [PATCH 2/3] block: cgroups, kconfig, build bits for BFQ-v5-3.2
Add a Kconfig option and do the related Makefile changes to compile
the BFQ I/O scheduler. Also let the cgroups subsystem know about the
BFQ I/O controller.
Signed-off-by: Fabio Checconi <fabio@gandalf.sssup.it>
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
---
block/Makefile | 1 +
include/linux/cgroup_subsys.h | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/block/Makefile b/block/Makefile
index 514c6e4..653d27b 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index ac663c1..c966638 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -64,3 +64,9 @@ SUBSYS(perf)
#endif
/* */
+
+#ifdef CONFIG_CGROUP_BFQIO
+SUBSYS(bfqio)
+#endif
+
+/* */
--
1.7.10.4

View File

@ -0,0 +1,69 @@
From 7a10d093f9779f42cb8d6affcb6a4436d3ebd6d3 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:41 -0700
Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken
userspace
The apparmor_parser when compiling policy could generate invalid dfas
that did not have sufficient padding to avoid invalid references, when
used by the kernel. The kernels check to verify the next/check table
size was broken meaning invalid dfas were being created by userspace
and not caught.
To remain compatible with old tools that are not fixed, pad the loaded
dfas next/check table. The dfa's themselves are valid except for the
high padding for potentially invalid transitions (high bounds error),
which have a maximimum is 256 entries. So just allocate an extra null filled
256 entries for the next/check tables. This will guarentee all bounds
are good and invalid transitions go to the null (0) state.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/match.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4..081491e 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -57,8 +57,17 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
if (bsize < tsize)
goto out;
+ /* Pad table allocation for next/check by 256 entries to remain
+ * backwards compatible with old (buggy) tools and remain safe without
+ * run time checks
+ */
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
+ tsize += 256 * th.td_flags;
+
table = kvmalloc(tsize);
if (table) {
+ /* ensure the pad is clear, else there will be errors */
+ memset(table, 0, tsize);
*table = th;
if (th.td_flags == YYTD_DATA8)
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
goto out;
if (flags & DFA_FLAG_VERIFY_STATES) {
+ int warning = 0;
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
/* TODO: do check that DEF state recursion terminates */
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (warning)
+ continue;
+ printk(KERN_WARNING "AppArmor DFA next/check "
+ "upper bounds error fixed, upgrade "
+ "user space tools \n");
+ warning = 1;
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;
--
1.7.5.4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,174 @@
diff --git a/block/blk-core.c b/block/blk-core.c
index d1a9a0a..8b54acb 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -73,6 +73,17 @@ static void drive_stat_acct(struct request *rq, int new_io)
part_inc_in_flight(part, rw);
}
+ switch (rw) { /* ATOP */
+ case READ: /* ATOP */
+ current->group_leader->stat.dsk_rio += new_io; /* ATOP */
+ current->group_leader->stat.dsk_rsz += blk_rq_sectors(rq); /* ATOP */
+ break; /* ATOP */
+ case WRITE: /* ATOP */
+ current->group_leader->stat.dsk_wio += new_io; /* ATOP */
+ current->group_leader->stat.dsk_wsz += blk_rq_sectors(rq); /* ATOP */
+ break; /* ATOP */
+ } /* ATOP */
+
part_stat_unlock();
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 13b5d07..cac522e 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -515,6 +515,25 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
(unsigned long long)delayacct_blkio_ticks(task),
cputime_to_clock_t(gtime),
cputime_to_clock_t(cgtime));
+
+ seq_printf(m, /* ATOP */
+ "%lu %llu %lu %llu %lu %llu %lu " /* ATOP */
+ "%llu %lu %llu %lu %llu %lu %lu\n", /* ATOP */
+ task->stat.dsk_rio, /* ATOP */
+ task->stat.dsk_rsz, /* ATOP */
+ task->stat.dsk_wio, /* ATOP */
+ task->stat.dsk_wsz, /* ATOP */
+ task->stat.tcp_snd, /* ATOP */
+ task->stat.tcp_ssz, /* ATOP */
+ task->stat.tcp_rcv, /* ATOP */
+ task->stat.tcp_rsz, /* ATOP */
+ task->stat.udp_snd, /* ATOP */
+ task->stat.udp_ssz, /* ATOP */
+ task->stat.udp_rcv, /* ATOP */
+ task->stat.udp_rsz, /* ATOP */
+ task->stat.raw_snd, /* ATOP */
+ task->stat.raw_rcv); /* ATOP */
+
if (mm)
mmput(mm);
return 0;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 78efe7c..22391bf 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1512,6 +1512,17 @@ struct task_struct {
#endif
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
+
+ struct { /* ATOP */
+ unsigned long dsk_rio, dsk_wio; /* ATOP */
+ unsigned long long dsk_rsz, dsk_wsz; /* ATOP */
+ unsigned long tcp_snd, tcp_rcv; /* ATOP */
+ unsigned long long tcp_ssz, tcp_rsz; /* ATOP */
+ unsigned long udp_snd, udp_rcv; /* ATOP */
+ unsigned long long udp_ssz, udp_rsz; /* ATOP */
+ unsigned long raw_snd, raw_rcv; /* ATOP */
+ } stat; /* ATOP */
+
/*
* cache last used pipe for splice
diff --git a/kernel/acct.c b/kernel/acct.c
index a6605ca..d5df53a 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -565,7 +565,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,
ac.ac_exitcode = pacct->ac_exitcode;
spin_unlock_irq(&current->sighand->siglock);
ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
- ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
+ ac.ac_rw = encode_comp_t(current->stat.dsk_rio + current->stat.dsk_wio); /* ATOP */
ac.ac_swaps = encode_comp_t(0);
/*
diff --git a/kernel/fork.c b/kernel/fork.c
index f88bd98..bab2085 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -683,6 +683,14 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
tsk->min_flt = tsk->maj_flt = 0;
tsk->nvcsw = tsk->nivcsw = 0;
+ tsk->stat.dsk_rio = tsk->stat.dsk_wio = 0; /* ATOP */
+ tsk->stat.dsk_rsz = tsk->stat.dsk_wsz = 0; /* ATOP */
+ tsk->stat.tcp_snd = tsk->stat.tcp_rcv = 0; /* ATOP */
+ tsk->stat.tcp_ssz = tsk->stat.tcp_rsz = 0; /* ATOP */
+ tsk->stat.udp_snd = tsk->stat.udp_rcv = 0; /* ATOP */
+ tsk->stat.udp_ssz = tsk->stat.udp_rsz = 0; /* ATOP */
+ tsk->stat.raw_snd = tsk->stat.raw_rcv = 0; /* ATOP */
+
#ifdef CONFIG_DETECT_HUNG_TASK
tsk->last_switch_count = tsk->nvcsw + tsk->nivcsw;
#endif
diff --git a/net/socket.c b/net/socket.c
index 769c386..3ba19f6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -547,10 +547,28 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
si->size = size;
err = security_socket_sendmsg(sock, msg, size);
- if (err)
- return err;
-
- return sock->ops->sendmsg(iocb, sock, msg, size);
+ if (!err)
+ err = sock->ops->sendmsg(iocb, sock, msg, size);
+
+ if (err >= 0 && sock->sk) { /* ATOP */
+ switch (sock->sk->sk_family) { /* ATOP */
+ case PF_INET: /* ATOP */
+ case PF_INET6: /* ATOP */
+ switch (sock->sk->sk_type) { /* ATOP */
+ case SOCK_STREAM: /* ATOP */
+ current->group_leader->stat.tcp_snd++; /* ATOP */
+ current->group_leader->stat.tcp_ssz+=size;/* ATOP */
+ break; /* ATOP */
+ case SOCK_DGRAM: /* ATOP */
+ current->group_leader->stat.udp_snd++; /* ATOP */
+ current->group_leader->stat.udp_ssz+=size;/* ATOP */
+ break; /* ATOP */
+ case SOCK_RAW: /* ATOP */
+ current->group_leader->stat.raw_snd++; /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ return err;
}
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
@@ -682,7 +700,29 @@ static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
{
int err = security_socket_recvmsg(sock, msg, size, flags);
- return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
+ if (!err)
+ err = __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
+
+ if (err >= 0 && sock->sk) { /* ATOP */
+ switch (sock->sk->sk_family) { /* ATOP */
+ case PF_INET: /* ATOP */
+ case PF_INET6: /* ATOP */
+ switch (sock->sk->sk_type) { /* ATOP */
+ case SOCK_STREAM: /* ATOP */
+ current->group_leader->stat.tcp_rcv++; /* ATOP */
+ current->group_leader->stat.tcp_rsz+=err; /* ATOP */
+ break; /* ATOP */
+ case SOCK_DGRAM: /* ATOP */
+ current->group_leader->stat.udp_rcv++; /* ATOP */
+ current->group_leader->stat.udp_rsz+=err; /* ATOP */
+ break; /* ATOP */
+ case SOCK_RAW: /* ATOP */
+ current->group_leader->stat.raw_rcv++; /* ATOP */
+ break; /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ return err;
}
int sock_recvmsg(struct socket *sock, struct msghdr *msg,

View File

@ -0,0 +1,125 @@
Index: linux-2.6.28/include/linux/acct.h
===================================================================
--- linux-2.6.28.orig/include/linux/acct.h 2009-01-14 13:02:24.000000000 +0100
+++ linux-2.6.28/include/linux/acct.h 2009-01-14 13:03:33.000000000 +0100
@@ -97,6 +97,54 @@
char ac_comm[ACCT_COMM]; /* Command Name */
};
+struct acct_atop
+{
+ char ac_flag; /* Flags */
+ char ac_version; /* Always set to ACCT_VERSION */
+ __u32 ac_pid; /* Process ID */
+ __u32 ac_ppid; /* Parent Process ID */
+ __u16 ac_uid16; /* LSB of Real User ID */
+ __u16 ac_gid16; /* LSB of Real Group ID */
+ __u16 ac_tty; /* Control Terminal */
+ __u32 ac_btime; /* Process Creation Time */
+ comp_t ac_utime; /* User Time */
+ comp_t ac_stime; /* System Time */
+ comp_t ac_etime; /* Elapsed Time */
+ comp_t ac_mem; /* Virtual Memory */
+ comp_t ac_rss; /* Resident Memory */
+ comp_t ac_io; /* Chars Transferred */
+ comp_t ac_rw; /* Blocks Read or Written */
+ comp_t ac_bread; /* Blocks Read */
+ comp_t ac_bwrite; /* Blocks Written */
+ comp2_t ac_dskrsz; /* Cum. blocks read */
+ comp2_t ac_dskwsz; /* Cum. blocks written */
+ comp_t ac_tcpsnd; /* TCP send requests */
+ comp_t ac_tcprcv; /* TCP recv requests */
+ comp2_t ac_tcpssz; /* TCP cum. length */
+ comp2_t ac_tcprsz; /* TCP cum. length */
+ comp_t ac_udpsnd; /* UDP send requests */
+ comp_t ac_udprcv; /* UDP recv requests */
+ comp2_t ac_udpssz; /* UDP cum. length */
+ comp2_t ac_udprsz; /* UDP cum. length */
+ comp_t ac_rawsnd; /* RAW send requests */
+ comp_t ac_rawrcv; /* RAW recv requests */
+ comp_t ac_minflt; /* Minor Pagefaults */
+ comp_t ac_majflt; /* Major Pagefaults */
+ comp_t ac_swaps; /* Number of Swaps */
+/* m68k had no padding here. */
+#if !defined(CONFIG_M68K) || !defined(__KERNEL__)
+ __u16 ac_ahz; /* AHZ */
+#endif
+ __u32 ac_exitcode; /* Exitcode */
+ char ac_comm[ACCT_COMM + 1]; /* Command Name */
+ __u8 ac_etime_hi; /* Elapsed Time MSB */
+ __u16 ac_etime_lo; /* Elapsed Time LSB */
+ __u32 ac_uid; /* Real User ID */
+ __u32 ac_gid; /* Real Group ID */
+};
+
+
+
/*
* accounting flags
*/
@@ -146,7 +194,13 @@
* 5: new binary incompatible format (128 bytes, second half)
*
*/
+#define CONFIG_PROCESS_ACCT_ATOP
+#ifdef CONFIG_PROCESS_ACCT_ATOP
+#define ACCT_VERSION 6
+#define AHZ (USER_HZ)
+typedef struct acct_atop acct_t;
+#else
#ifdef CONFIG_BSD_PROCESS_ACCT_V3
#define ACCT_VERSION 3
#define AHZ 100
@@ -160,6 +214,7 @@
#define AHZ (USER_HZ)
typedef struct acct acct_t;
#endif
+#endif
#else
#define ACCT_VERSION 2
Index: linux-2.6.28/kernel/acct.c
===================================================================
--- linux-2.6.28.orig/kernel/acct.c 2009-01-14 13:03:31.000000000 +0100
+++ linux-2.6.28/kernel/acct.c 2009-01-14 13:03:33.000000000 +0100
@@ -405,7 +405,7 @@
return exp;
}
-#if ACCT_VERSION==1 || ACCT_VERSION==2
+#if ACCT_VERSION==1 || ACCT_VERSION==2 || ACCT_VERSION==6
/*
* encode an u64 into a comp2_t (24 bits)
*
@@ -552,6 +552,30 @@
ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns);
rcu_read_unlock();
#endif
+#if ACCT_VERSION==6 /* ATOP */
+ ac.ac_pid = current->pid;
+ ac.ac_ppid = current->parent->pid;
+ ac.ac_uid16 = ac.ac_uid;
+ ac.ac_gid16 = ac.ac_gid;
+ ac.ac_ahz = AHZ;
+ ac.ac_bread = encode_comp_t(current->stat.dsk_rio);
+ ac.ac_bwrite = encode_comp_t(current->stat.dsk_wio);
+ ac.ac_dskrsz = encode_comp2_t(current->stat.dsk_rsz);
+ ac.ac_dskwsz = encode_comp2_t(current->stat.dsk_wsz);
+ ac.ac_tcpsnd = encode_comp_t(current->stat.tcp_snd);
+ ac.ac_tcprcv = encode_comp_t(current->stat.tcp_rcv);
+ ac.ac_tcpssz = encode_comp2_t(current->stat.tcp_ssz);
+ ac.ac_tcprsz = encode_comp2_t(current->stat.tcp_rsz);
+ ac.ac_udpsnd = encode_comp_t(current->stat.udp_snd);
+ ac.ac_udprcv = encode_comp_t(current->stat.udp_rcv);
+ ac.ac_udpssz = encode_comp2_t(current->stat.udp_ssz);
+ ac.ac_udprsz = encode_comp2_t(current->stat.udp_rsz);
+ ac.ac_rawsnd = encode_comp_t(current->stat.raw_snd);
+ ac.ac_rawrcv = encode_comp_t(current->stat.raw_rcv);
+ ac.ac_rss = current->mm ?
+ encode_comp_t(get_mm_rss(current->mm)<<(PAGE_SHIFT-10)) :
+ encode_comp_t(0);
+#endif
spin_lock_irq(&current->sighand->siglock);
tty = current->signal->tty; /* Safe as we hold the siglock */

9093
3.2.34/3.2.0-ck1.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
3rdparty/mkbuild.pl | 92 +++++++++++++++++++++++++++++++++++++++++++++
Documentation/3rdparty.txt | 76 +++++++++++++++++++++++++++++++++++++
2 files changed, 168 insertions(+)
diff -Nurp linux-2.6.37/3rdparty/mkbuild.pl 3rdparty/mkbuild.pl
--- linux-2.6.37/3rdparty/mkbuild.pl 1970-01-01 02:00:00.000000000 +0200
+++ 3rdparty/mkbuild.pl 2004-04-23 14:59:03.000000000 +0300
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+#
+# Version 1.0
+#
+# Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+# Copyright 2002 Juan Quintela <quintela@mandrakesoft.com>
+# Copyright 2003 Nicolas Planel <nplanel@mandrakesoft.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+#
+#
+# Run "mkbuild.pl"
+#
+# This program generates the following files
+# Makefile
+# Makefile.drivers
+# Config.in
+# using the information in the subdirs of this directory.
+#
+# subdirs need to have:
+# a Config.in file
+# a Makefile with a O_TARGET/L_TARGET targets
+# The config.in should set a CONFIG_<module_dir_name> to m/y.
+
+use strict;
+
+opendir(THISDIR, ".");
+# get dirs without . and .. garbage
+my (@modules) = grep(!/\.\.?$/,grep(-d, readdir(THISDIR)));
+closedir(THISDIR);
+
+generate_kconfig(@modules);
+generate_makefile(@modules);
+exit(0);
+
+##########################################################################
+
+sub generate_makefile {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Makefile" or die "Cannot create new Makefile: $!\n";
+ print F <<'EOM';
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+EOM
+ printf F "obj- := 3rdparty.o # Dummy rule to force built-in.o to be made\n";
+ printf F "obj-\$(%s) += %s\n", to_CONFIG($_), $_ . '/' foreach @modules;
+}
+
+sub generate_kconfig {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Kconfig" or die "Cannot create Kconfig: $!\n";
+ print F <<"EOM";
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+menu "Unofficial 3rd party kernel additions"
+
+EOM
+
+ foreach (@modules) {
+ die "No Kconfig in $_.\n" if ! -r "$_/Kconfig";
+ print F "source 3rdparty/$_/Kconfig\n";
+ }
+ print F "\n\nendmenu\n";
+}
+
+sub to_CONFIG {
+ local $_ = $_[0];
+ tr/a-z/A-Z/;
+ s/[\-\. ]/_/g;
+ "CONFIG_$_";
+}
+
+sub find_target {
+ my ($module_dir) = @_;
+
+ local *F;
+ open(F, "$module_dir/Makefile") or die "$module_dir/Makefile: $!\n";
+ while (<F>) {
+ chomp;
+ return $1 if (/[LO]_TARGET.*:=\s+(\S+)/);
+ }
+}
+
diff -Nurp linux-2.6.37/Documentation/3rdparty.txt Documentation/3rdparty.txt
--- linux-2.6.37/Documentation/3rdparty.txt 1970-01-01 02:00:00.000000000 +0200
+++ Documentation/3rdparty.txt 2003-11-22 01:07:26.000000000 +0200
@@ -0,0 +1,76 @@
+
+Third-Party Kernel Source Module Support, or
+an easy way to add modules to your kernel build.
+
+
+
+Vendors quite often add additional drivers and features to the kernel
+which require nothing more than modifying Kconfig, Makefile, and
+adding one or more files to a sub-directory. As a single discrete task,
+this is not a problem. However, using patches to add modules to the
+kernel very often results in patch conflicts, resulting in needless time
+wastage as developers regenerate an otherwise working kernel patch.
+
+This is designed as a solution to these problems. It is NOT designed as
+a replacement for the kernel build system, but merely as a tool for
+vendors and system administrators to ease the pain of patch management.
+
+The key feature of this system is the distinct lack of patches. Drivers
+are installed via unpacking a tarball.
+
+
+
+Adding a directory to the build (usually from a tarball)
+--------------------------------------------------------
+If a directory exists inside the 3rdparty sub-directory that contains a
+proper Makefile, it can be added to the build. It also needs a
+Kconfig file.
+
+ cd /usr/src/linux-2.4.3/3rdparty
+ bzcat /tmp/my-driver2.tar.bz2 | tar xf - # creates "my2" dir
+
+
+Limitations
+-----------
+There are some limitations to this system. This system is only
+designed to support a very common case. If you find yourself running
+into limitations (kernel build experts can spot them right off),
+then you should probably be patching the kernel instead of using
+mkbuild.pl for that particular module.
+
+FIXME: actually list the limitations
+
+
+
+Other notes
+-----------
+Link order is controlled by the order of mkbuild.pl executions.
+
+"make mrproper" will erase Makefile.meta, and empty Kconfig, Makefile,
+and Makefile.drivers.
+
+IMPORTANT NOTE: Because this feature modifies the kernel's makefiles and
+configuration system, you MUST complete all mkbuild.pl runs before
+running any "make" command.
+
+Building in the 3rdparty dir
+----------------------------
+
+If you use modules that:
+ - are contained in one subdir with the name of the module
+ - has a Makefile
+ - has a Kconfig file
+
+The system calls the ./mkbuild.pl script. It will search for
+subdirectories, and will try to build each of them as a module.
+Things to note:
+
+ The dependencies will be done in a module called:
+
+ 3rdparty/<module_dir_name>/<module_name>
+
+depending of CONFIG_<module_name_in_uppercase>.
+
+<module_name> is the value of O_TARGET/L_TARGET.
+
+

View File

@ -0,0 +1,372 @@
Submitted By: Mario Fetka (mario dot fetka at gmail dot com)
Date: 2012-11-18
Initial Package Version: 3.2.33
Origin: openwtr.org packages/system/button-hotplug
Upstream Status: unknown
Description: create uevents from button usage
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/Kconfig 3rdparty/button_hotplug/Kconfig
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/Kconfig 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/Kconfig 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,2 @@
+config BUTTON_HOTPLUG
+ tristate "Button Hotplug driver"
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/Makefile 3rdparty/button_hotplug/Makefile
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/Makefile 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1 @@
+obj-${CONFIG_BUTTON_HOTPLUG} += button-hotplug.o
\ No newline at end of file
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/button-hotplug.c 3rdparty/button_hotplug/button-hotplug.c
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/button-hotplug.c 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/button-hotplug.c 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,349 @@
+/*
+ * Button Hotplug driver
+ *
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+#include <linux/input.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+
+#define DRV_NAME "button-hotplug"
+#define DRV_VERSION "0.4.1"
+#define DRV_DESC "Button Hotplug driver"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+#ifndef BIT_MASK
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#endif
+
+struct bh_priv {
+ unsigned long *seen;
+ struct input_handle handle;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = handle->private;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen[btn]) / HZ, value);
+ priv->seen[btn] = seen;
+}
+#else
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+static int button_hotplug_connect(struct input_handler *handler,
+ struct input_dev *dev, const struct input_device_id *id)
+{
+ struct bh_priv *priv;
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (test_bit(button_map[i].code, dev->keybit))
+ break;
+
+ if (i == ARRAY_SIZE(button_map))
+ return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv) +
+ (sizeof(unsigned long) * ARRAY_SIZE(button_map)),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->seen = (unsigned long *) &priv[1];
+ priv->handle.private = priv;
+ priv->handle.dev = dev;
+ priv->handle.handler = handler;
+ priv->handle.name = DRV_NAME;
+
+ ret = input_register_handle(&priv->handle);
+ if (ret)
+ goto err_free_priv;
+
+ ret = input_open_device(&priv->handle);
+ if (ret)
+ goto err_unregister_handle;
+
+ BH_DBG("connected to %s\n", dev->name);
+
+ return 0;
+
+ err_unregister_handle:
+ input_unregister_handle(&priv->handle);
+
+ err_free_priv:
+ kfree(priv);
+ return ret;
+}
+
+static void button_hotplug_disconnect(struct input_handle *handle)
+{
+ struct bh_priv *priv = handle->private;
+
+ input_close_device(handle);
+ input_unregister_handle(handle);
+
+ kfree(priv);
+}
+
+static const struct input_device_id button_hotplug_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ },
+ {
+ /* Terminating entry */
+ },
+};
+
+MODULE_DEVICE_TABLE(input, button_hotplug_ids);
+
+static struct input_handler button_hotplug_handler = {
+ .event = button_hotplug_event,
+ .connect = button_hotplug_connect,
+ .disconnect = button_hotplug_disconnect,
+ .name = DRV_NAME,
+ .id_table = button_hotplug_ids,
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int __init button_hotplug_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+ ret = input_register_handler(&button_hotplug_handler);
+ if (ret)
+ BH_ERR("unable to register input handler\n");
+
+ return ret;
+}
+module_init(button_hotplug_init);
+
+static void __exit button_hotplug_exit(void)
+{
+ input_unregister_handler(&button_hotplug_handler);
+}
+module_exit(button_hotplug_exit);
+
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+

View File

@ -0,0 +1,472 @@
Submitted By: Mario Fetka (mario dot fetka at gmail dot com)
Date: 2012-11-18
Initial Package Version: 3.2.33
Origin: openwtr.org packages/system/gpio-button-hotplug
Upstream Status: unknown
Description: gpio button uevent
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Kconfig 3rdparty/gpio_button_hotplug/Kconfig
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Kconfig 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/Kconfig 2012-11-18 18:41:43.048939468 +0000
@@ -0,0 +1,2 @@
+config GPIO_BUTTON_HOTPLUG
+ tristate "GPIO Button Hotplug driver"
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Makefile 3rdparty/gpio_button_hotplug/Makefile
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/Makefile 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1 @@
+obj-${CONFIG_GPIO_BUTTON_HOTPLUG} += gpio-button-hotplug.o
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 3rdparty/gpio_button_hotplug/gpio-button-hotplug.c
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,450 @@
+/*
+ * GPIO Button Hotplug driver
+ *
+ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#define DRV_NAME "gpio-keys-polled"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+struct bh_priv {
+ unsigned long seen;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+struct gpio_keys_button_data {
+ struct delayed_work work;
+ struct bh_priv bh;
+ int last_state;
+ int count;
+ int threshold;
+ int can_sleep;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = &data->bh;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen) / HZ, value);
+ priv->seen = seen;
+}
+#else
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+struct gpio_keys_polled_dev {
+ struct delayed_work work;
+
+ struct device *dev;
+ struct gpio_keys_platform_data *pdata;
+ struct gpio_keys_button_data data[0];
+};
+
+static void gpio_keys_polled_check_state(struct gpio_keys_button *button,
+ struct gpio_keys_button_data *bdata)
+{
+ int state;
+
+ if (bdata->can_sleep)
+ state = !!gpio_get_value_cansleep(button->gpio);
+ else
+ state = !!gpio_get_value(button->gpio);
+
+ state = !!(state ^ button->active_low);
+ if (state != bdata->last_state) {
+ unsigned int type = button->type ?: EV_KEY;
+
+ button_hotplug_event(bdata, type, button->code, state);
+ bdata->count = 0;
+ bdata->last_state = state;
+ }
+}
+
+static void gpio_keys_polled_queue_work(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ unsigned long delay = msecs_to_jiffies(pdata->poll_interval);
+
+ if (delay >= HZ)
+ delay = round_jiffies_relative(delay);
+ schedule_delayed_work(&bdev->work, delay);
+}
+
+static void gpio_keys_polled_poll(struct work_struct *work)
+{
+ struct gpio_keys_polled_dev *bdev =
+ container_of(work, struct gpio_keys_polled_dev, work.work);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ for (i = 0; i < bdev->pdata->nbuttons; i++) {
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+ if (bdata->count < bdata->threshold)
+ bdata->count++;
+ else
+ gpio_keys_polled_check_state(&pdata->buttons[i], bdata);
+ }
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devinit gpio_keys_polled_open(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ if (pdata->enable)
+ pdata->enable(bdev->dev);
+
+ /* report initial state of the buttons */
+ for (i = 0; i < pdata->nbuttons; i++)
+ gpio_keys_polled_check_state(&pdata->buttons[i], &bdev->data[i]);
+
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devexit gpio_keys_polled_close(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+ cancel_delayed_work_sync(&bdev->work);
+
+ if (pdata->disable)
+ pdata->disable(bdev->dev);
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct gpio_keys_polled_dev *bdev;
+ int error;
+ int i;
+
+ if (!pdata || !pdata->poll_interval)
+ return -EINVAL;
+
+ bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+ pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+ GFP_KERNEL);
+ if (!bdev) {
+ dev_err(dev, "no memory for private data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+ unsigned int gpio = button->gpio;
+
+ if (button->wakeup) {
+ dev_err(dev, DRV_NAME " does not support wakeup\n");
+ error = -EINVAL;
+ goto err_free_gpio;
+ }
+
+ error = gpio_request(gpio,
+ button->desc ? button->desc : DRV_NAME);
+ if (error) {
+ dev_err(dev, "unable to claim gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ error = gpio_direction_input(gpio);
+ if (error) {
+ dev_err(dev,
+ "unable to set direction on gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ bdata->can_sleep = gpio_cansleep(gpio);
+ bdata->last_state = 0;
+ bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+ pdata->poll_interval);
+ }
+
+ bdev->dev = &pdev->dev;
+ bdev->pdata = pdata;
+ platform_set_drvdata(pdev, bdev);
+
+ INIT_DELAYED_WORK(&bdev->work, gpio_keys_polled_poll);
+
+ gpio_keys_polled_open(bdev);
+
+ return 0;
+
+err_free_gpio:
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+ struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i = pdata->nbuttons;
+
+ gpio_keys_polled_close(bdev);
+
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+ .probe = gpio_keys_polled_probe,
+ .remove = __devexit_p(gpio_keys_polled_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+ return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+ platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons hotplug driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
diff -uNr linux-3.2.33-go.orig/arch/alpha/Kconfig linux-3.2.33-go/arch/alpha/Kconfig
--- linux-3.2.33-go.orig/arch/alpha/Kconfig 2012-11-15 22:08:02.768806792 +0100
+++ linux-3.2.33-go/arch/alpha/Kconfig 2012-11-15 22:08:29.937483632 +0100
@@ -673,3 +673,4 @@
source "lib/Kconfig"
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/arm/Kconfig linux-3.2.33-go/arch/arm/Kconfig
--- linux-3.2.33-go.orig/arch/arm/Kconfig 2012-11-15 22:07:59.952839378 +0100
+++ linux-3.2.33-go/arch/arm/Kconfig 2012-11-15 22:14:01.950566716 +0100
@@ -2259,3 +2259,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/ia64/Kconfig linux-3.2.33-go/arch/ia64/Kconfig
--- linux-3.2.33-go.orig/arch/ia64/Kconfig 2012-11-15 22:08:00.893828523 +0100
+++ linux-3.2.33-go/arch/ia64/Kconfig 2012-11-15 22:08:29.938483621 +0100
@@ -669,3 +669,5 @@
config IOMMU_HELPER
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/mips/Kconfig linux-3.2.33-go/arch/mips/Kconfig
--- linux-3.2.33-go.orig/arch/mips/Kconfig 2012-11-15 22:08:02.698807597 +0100
+++ linux-3.2.33-go/arch/mips/Kconfig 2012-11-15 22:08:29.939483610 +0100
@@ -2485,3 +2485,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/powerpc/Kconfig linux-3.2.33-go/arch/powerpc/Kconfig
--- linux-3.2.33-go.orig/arch/powerpc/Kconfig 2012-11-15 22:08:01.893816938 +0100
+++ linux-3.2.33-go/arch/powerpc/Kconfig 2012-11-15 22:08:29.940483598 +0100
@@ -980,3 +980,5 @@
bool
source "arch/powerpc/kvm/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/sparc/Kconfig linux-3.2.33-go/arch/sparc/Kconfig
--- linux-3.2.33-go.orig/arch/sparc/Kconfig 2012-11-15 22:08:00.130837331 +0100
+++ linux-3.2.33-go/arch/sparc/Kconfig 2012-11-15 22:08:29.941483586 +0100
@@ -605,3 +605,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/x86/Kconfig linux-3.2.33-go/arch/x86/Kconfig
--- linux-3.2.33-go.orig/arch/x86/Kconfig 2012-11-15 22:08:00.435833823 +0100
+++ linux-3.2.33-go/arch/x86/Kconfig 2012-11-15 22:08:29.945483540 +0100
@@ -2179,3 +2179,5 @@
source "arch/x86/kvm/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/Makefile linux-3.2.33-go/Makefile
--- linux-3.2.33-go.orig/Makefile 2012-11-15 22:08:03.435799123 +0100
+++ linux-3.2.33-go/Makefile 2012-11-15 22:08:29.946483529 +0100
@@ -507,7 +507,7 @@
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
-drivers-y := drivers/ sound/ firmware/
+drivers-y := drivers/ sound/ firmware/ 3rdparty/
net-y := net/
libs-y := lib/
core-y := usr/
diff -uNr linux-3.2.33-go.orig/scripts/kconfig/Makefile linux-3.2.33-go/scripts/kconfig/Makefile
--- linux-3.2.33-go.orig/scripts/kconfig/Makefile 2012-11-15 22:07:58.064861094 +0100
+++ linux-3.2.33-go/scripts/kconfig/Makefile 2012-11-15 22:08:55.603180188 +0100
@@ -11,29 +11,29 @@
Kconfig := Kconfig
endif
-xconfig: $(obj)/qconf
+xconfig: $(obj)/qconf 3rdparty/Makefile
$< $(Kconfig)
-gconfig: $(obj)/gconf
+gconfig: $(obj)/gconf 3rdparty/Makefile
$< $(Kconfig)
-menuconfig: $(obj)/mconf
+menuconfig: $(obj)/mconf 3rdparty/Makefile
$< $(Kconfig)
-config: $(obj)/conf
+config: $(obj)/conf 3rdparty/Makefile
$< --oldaskconfig $(Kconfig)
-nconfig: $(obj)/nconf
+nconfig: $(obj)/nconf 3rdparty/Makefile
$< $(Kconfig)
-oldconfig: $(obj)/conf
+oldconfig: $(obj)/conf 3rdparty/Makefile
$< --$@ $(Kconfig)
-silentoldconfig: $(obj)/conf
+silentoldconfig: $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/generated
$< --$@ $(Kconfig)
-localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/generated
$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
$(Q)if [ -f .config ]; then \
@@ -90,18 +90,18 @@
*) cat $(CLONECONFIG) > .config.running ;; \
esac && \
echo -e "Cloning configuration file $(CLONECONFIG)\n"
- $(Q)$< --defconfig=.config.running arch/$(SRCARCH)/Kconfig
+ $(Q)$< --defconfig=.config.running arch/$(SRCARCH)/Kconfig 3rdparty/Makefile
PHONY += listnewconfig oldnoconfig savedefconfig defconfig
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig oldnoconfig: $(obj)/conf 3rdparty/Makefile
$< --$@ $(Kconfig)
-savedefconfig: $(obj)/conf
+savedefconfig: $(obj)/conf 3rdparty/Makefile
$< --$@=defconfig $(Kconfig)
-defconfig: $(obj)/conf
+defconfig: $(obj)/conf 3rdparty/Makefile
ifeq ($(KBUILD_DEFCONFIG),)
$< --defconfig $(Kconfig)
else
@@ -109,7 +109,7 @@
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
endif
-%_defconfig: $(obj)/conf
+%_defconfig: $(obj)/conf 3rdparty/Makefile
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Help text used by make help
@@ -186,6 +186,8 @@
gconf-target := 1
endif
+3rdparty/Makefile:
+ pushd $(srctree)/3rdparty ; $(PERL) ./mkbuild.pl ; popd
ifeq ($(qconf-target),1)
hostprogs-y += qconf

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -50,6 +50,18 @@ static const char *kobject_actions[] = {
[KOBJ_OFFLINE] = "offline",
};
+u64 uevent_next_seqnum(void)
+{
+ u64 seq;
+
+ mutex_lock(&uevent_sock_mutex);
+ seq = ++uevent_seqnum;
+ mutex_unlock(&uevent_sock_mutex);
+
+ return seq;
+}
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
+
/**
* kobject_action_type - translate action string to numeric type
*

View File

@ -0,0 +1,85 @@
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -31,6 +31,8 @@
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
+struct sk_buff;
+
/* path to the userspace helper executed on an event */
extern char uevent_helper[];
@@ -213,6 +215,10 @@ int add_uevent_var(struct kobj_uevent_en
int kobject_action_type(const char *buf, size_t count,
enum kobject_action *type);
+
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation);
+
#else
static inline int kobject_uevent(struct kobject *kobj,
enum kobject_action action)
@@ -229,6 +235,16 @@ int add_uevent_var(struct kobj_uevent_en
static inline int kobject_action_type(const char *buf, size_t count,
enum kobject_action *type)
{ return -EINVAL; }
+
+void kfree_skb(struct sk_buff *);
+
+static inline int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation)
+{
+ kfree_skb(skb);
+ return 0;
+}
+
#endif
#endif /* _KOBJECT_H_ */
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -381,6 +381,43 @@ int add_uevent_var(struct kobj_uevent_en
EXPORT_SYMBOL_GPL(add_uevent_var);
#if defined(CONFIG_NET)
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation)
+{
+ struct uevent_sock *ue_sk;
+ int err = 0;
+
+ /* send netlink message */
+ mutex_lock(&uevent_sock_mutex);
+ list_for_each_entry(ue_sk, &uevent_sock_list, list) {
+ struct sock *uevent_sock = ue_sk->sk;
+ struct sk_buff *skb2;
+
+ skb2 = skb_clone(skb, allocation);
+ if (!skb2)
+ break;
+
+ err = netlink_broadcast(uevent_sock, skb2, pid, group,
+ allocation);
+ if (err)
+ break;
+ }
+ mutex_unlock(&uevent_sock_mutex);
+
+ kfree_skb(skb);
+ return err;
+}
+#else
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation)
+{
+ kfree_skb(skb);
+ return 0;
+}
+#endif
+EXPORT_SYMBOL_GPL(broadcast_uevent);
+
+#if defined(CONFIG_NET)
static int uevent_net_init(struct net *net)
{
struct uevent_sock *ue_sk;

View File

@ -0,0 +1,145 @@
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index 182f9ff..907a5de 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -74,6 +74,26 @@ config VFAT_FS
To compile this as a module, choose M here: the module will be called
vfat.
+config VFAT_FS_DUALNAMES
+ bool "VFAT dual names support"
+ depends on VFAT_FS
+ help
+ This option provides support for dual filenames on VFAT filesystems.
+ If this option is disabled then file creation will either put
+ a short (8.3) name or a long name on the file, but never both.
+ The field where a shortname would normally go is filled with
+ invalid characters such that it cannot be considered a valid
+ short filename.
+
+ That means that long filenames created with this option
+ disabled will not be accessible at all to operating systems
+ that do not understand the VFAT extensions.
+
+ Users considering enabling this option should consider the implications
+ of any patents that may exist on dual filenames in VFAT.
+
+ If unsure, say N
+
config FAT_DEFAULT_CODEPAGE
int "Default codepage for FAT"
depends on MSDOS_FS || VFAT_FS
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 38ff75a..cd5d3ec 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -415,14 +415,13 @@
}
i += chl;
}
- if (!last_u)
- continue;
-
- /* Compare shortname */
- bufuname[last_u] = 0x0000;
- len = fat_uni_to_x8(sb, bufuname, bufname, sizeof(bufname));
- if (fat_name_match(sbi, name, name_len, bufname, len))
- goto found;
+ if (last_u) {
+ /* Compare shortname */
+ bufuname[last_u] = 0x0000;
+ len = fat_uni_to_x8(sb, bufuname, bufname, sizeof(bufname));
+ if (fat_name_match(sbi, name, name_len, bufname, len))
+ goto found;
+ }
if (nr_slots) {
void *longname = unicode + FAT_MAX_UNI_CHARS;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 73471b7..894f44d 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -22,6 +22,7 @@
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include <linux/namei.h>
+#include <linux/random.h>
#include "fat.h"
/*
@@ -586,6 +587,59 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
return 0;
}
+#ifndef CONFIG_VFAT_FS_DUALNAMES
+/*
+ * build a 11 byte 8.3 buffer which is not a short filename. We want 11
+ * bytes which:
+ * - will be seen as a constant string to all APIs on Linux and Windows
+ * - cannot be matched with wildcard patterns
+ * - cannot be used to access the file
+ * - has a low probability of collision within a directory
+ * - has an invalid 3 byte extension
+ * - contains at least one non-space and non-nul byte
+ */
+static void vfat_build_dummy_83_buffer(struct inode *dir, char *msdos_name)
+{
+ u32 rand_num = random32() & 0x3FFFFFFF;
+ int i;
+
+ /* a value of zero would leave us with only nul and spaces,
+ * which would not work with older linux systems
+ */
+ if (rand_num == 0)
+ rand_num = 1;
+
+ /* we start with a space followed by nul as spaces at the
+ * start of an entry are trimmed in FAT, which means that
+ * starting the 11 bytes with 0x20 0x00 gives us a value which
+ * cannot be used to access the file. It also means that the
+ * value as seen from all Windows and Linux APIs is a constant
+ */
+ msdos_name[0] = ' ';
+ msdos_name[1] = 0;
+
+ /* we use / and 2 nul bytes for the extension. These are
+ * invalid in FAT and mean that utilities that show the
+ * directory show no extension, but still work via the long
+ * name for old Linux kernels
+ */
+ msdos_name[8] = '/';
+ msdos_name[9] = 0;
+ msdos_name[10] = 0;
+
+ /*
+ * fill the remaining 6 bytes with random invalid values
+ * This gives us a low collision rate, which means a low
+ * chance of problems with chkdsk.exe and WindowsXP
+ */
+ for (i = 2; i < 8; i++) {
+ msdos_name[i] = rand_num & 0x1F;
+ rand_num >>= 5;
+ }
+}
+#endif
+
+
static int vfat_build_slots(struct inode *dir, const unsigned char *name,
int len, int is_dir, int cluster,
struct timespec *ts,
@@ -628,6 +682,11 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
goto shortname;
}
+#ifndef CONFIG_VFAT_FS_DUALNAMES
+ vfat_build_dummy_83_buffer(dir, msdos_name);
+ lcase = 0;
+#endif
+
/* build the entry of long file name */
cksum = fat_checksum(msdos_name);
--
1.6.0.4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
>From 9f04e51293b130474504216a477bb2a73cbf59e1 Mon Sep 17 00:00:00 2001
From: Anssi Hannula <anssi.hannula@iki.fi>
Date: Thu, 22 Mar 2012 22:29:11 +0200
Subject: [PATCH] ata: prefer ata drivers over ide drivers when both are built
Currently the old IDE drivers are preferred over ATA drivers when both
are built, since ide/ is listed first in drivers/Makefile and therefore
the IDE drivers end up before ATA drivers in modules.order which is used
by depmod/modprobe for module ordering.
Change it so that ATA drivers are preferred over IDE driver by moving
the ide/ entry under ata/ in drivers/Makefile.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
---
drivers/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/Makefile b/drivers/Makefile
index 932e8bf..e8df3d0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -47,9 +47,9 @@ obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ nfc/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
-obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
+obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
--
1.7.9.3

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,238 @@
diff --git a/Makefile b/Makefile
index e13e4e7..fa5acc83 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 2
-SUBLEVEL = 25
+SUBLEVEL = 26
EXTRAVERSION =
NAME = Saber-toothed Squirrel
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index bb3ee36..f7c89e2 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -99,7 +99,6 @@ struct cpuinfo_x86 {
u16 apicid;
u16 initial_apicid;
u16 x86_clflush_size;
-#ifdef CONFIG_SMP
/* number of cores as seen by the OS: */
u16 booted_cores;
/* Physical processor id: */
@@ -110,7 +109,6 @@ struct cpuinfo_x86 {
u8 compute_unit_id;
/* Index into per_cpu list: */
u16 cpu_index;
-#endif
u32 microcode;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index bae1efe..be16854 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -154,16 +154,14 @@ int amd_get_subcaches(int cpu)
{
struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
unsigned int mask;
- int cuid = 0;
+ int cuid;
if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return 0;
pci_read_config_dword(link, 0x1d4, &mask);
-#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
-#endif
return (mask >> (4 * cuid)) & 0xf;
}
@@ -172,7 +170,7 @@ int amd_set_subcaches(int cpu, int mask)
static unsigned int reset, ban;
struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
unsigned int reg;
- int cuid = 0;
+ int cuid;
if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING) || mask > 0xf)
return -EINVAL;
@@ -190,9 +188,7 @@ int amd_set_subcaches(int cpu, int mask)
pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
}
-#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
-#endif
mask <<= 4 * cuid;
mask |= (0xf ^ (1 << cuid)) << 26;
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 3524e1f..ff8557e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -148,7 +148,6 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)
static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
if (!c->cpu_index)
return;
@@ -192,7 +191,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
valid_k7:
;
-#endif
}
static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index aa003b1..ca93cc7 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -676,9 +676,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
-#ifdef CONFIG_SMP
c->cpu_index = 0;
-#endif
filter_cpuid_features(c, false);
setup_smep(c);
@@ -764,10 +762,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
c->apicid = c->initial_apicid;
# endif
#endif
-
-#ifdef CONFIG_X86_HT
c->phys_proc_id = c->initial_apicid;
-#endif
}
setup_smep(c);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 5231312..3e6ff6c 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -181,7 +181,6 @@ static void __cpuinit trap_init_f00f_bug(void)
static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
if (!c->cpu_index)
return;
@@ -198,7 +197,6 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: SMP operation may be unreliable"
"with B stepping processors.\n");
}
-#endif
}
static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b0f1271..3b67877 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -119,9 +119,7 @@ void mce_setup(struct mce *m)
m->time = get_seconds();
m->cpuvendor = boot_cpu_data.x86_vendor;
m->cpuid = cpuid_eax(1);
-#ifdef CONFIG_SMP
m->socketid = cpu_data(m->extcpu).phys_proc_id;
-#endif
m->apicid = cpu_data(m->extcpu).initial_apicid;
rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 445a61c..d4444be 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -65,11 +65,9 @@ struct threshold_bank {
};
static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks);
-#ifdef CONFIG_SMP
static unsigned char shared_bank[NR_BANKS] = {
0, 0, 0, 0, 1
};
-#endif
static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */
@@ -227,10 +225,9 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (!block)
per_cpu(bank_map, cpu) |= (1 << bank);
-#ifdef CONFIG_SMP
+
if (shared_bank[bank] && c->cpu_core_id)
break;
-#endif
memset(&b, 0, sizeof(b));
b.cpu = cpu;
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 14b2314..8022c66 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -64,12 +64,10 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
static int show_cpuinfo(struct seq_file *m, void *v)
{
struct cpuinfo_x86 *c = v;
- unsigned int cpu = 0;
+ unsigned int cpu;
int i;
-#ifdef CONFIG_SMP
cpu = c->cpu_index;
-#endif
seq_printf(m, "processor\t: %u\n"
"vendor_id\t: %s\n"
"cpu family\t: %d\n"
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 18a1293..0db57b5 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -1609,11 +1609,9 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
mce->cpuvendor, mce->cpuid, mce->time,
mce->socketid, mce->apicid);
-#ifdef CONFIG_SMP
/* Only handle if it is the right mc controller */
if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
return NOTIFY_DONE;
-#endif
smp_rmb();
if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 0790c98..19b4412 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -57,16 +57,15 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
-#ifdef CONFIG_SMP
#define TO_PHYS_ID(cpu) cpu_data(cpu).phys_proc_id
#define TO_CORE_ID(cpu) cpu_data(cpu).cpu_core_id
+#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
+
+#ifdef CONFIG_SMP
#define for_each_sibling(i, cpu) for_each_cpu(i, cpu_sibling_mask(cpu))
#else
-#define TO_PHYS_ID(cpu) (cpu)
-#define TO_CORE_ID(cpu) (cpu)
#define for_each_sibling(i, cpu) for (i = 0; false; )
#endif
-#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
/*
* Per-Core Temperature Data

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

41
3.2.34/cloneconfig.patch Normal file
View File

@ -0,0 +1,41 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Add ``cloneconfig'' target
Patch-mainline: Submitted 24 Feb 2011
Cloneconfig takes the first configuration it finds which appears
to belong to the running kernel, and configures the kernel sources
to match this configuration as closely as possible.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
scripts/kconfig/Makefile | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -99,6 +99,23 @@ PHONY += allnoconfig allyesconfig allmod
allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
$< --$@ $(Kconfig)
+
+UNAME_RELEASE := $(shell uname -r)
+CLONECONFIG := $(firstword $(wildcard /proc/config.gz \
+ /lib/modules/$(UNAME_RELEASE)/.config \
+ /etc/kernel-config \
+ /boot/config-$(UNAME_RELEASE)))
+cloneconfig: $(obj)/conf
+ $(Q)case "$(CLONECONFIG)" in \
+ '') echo -e "The configuration of the running" \
+ "kernel could not be determined\n"; \
+ false ;; \
+ *.gz) gzip -cd $(CLONECONFIG) > .config.running ;; \
+ *) cat $(CLONECONFIG) > .config.running ;; \
+ esac && \
+ echo -e "Cloning configuration file $(CLONECONFIG)\n"
+ $(Q)$< --defconfig=.config.running arch/$(SRCARCH)/Kconfig
+
PHONY += listnewconfig oldnoconfig savedefconfig defconfig

View File

@ -0,0 +1,337 @@
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/arch/x86/kernel/early_printk.c linux-2.6.29.3-cprintk/arch/x86/kernel/early_printk.c
--- a/arch/x86/kernel/early_printk.c 2009-03-24 00:12:14.000000000 +0100
+++ b/arch/x86/kernel/early_printk.c 2009-05-09 16:10:36.000000000 +0200
@@ -23,7 +23,8 @@
static int max_ypos = 25, max_xpos = 80;
static int current_ypos = 25, current_xpos;
-static void early_vga_write(struct console *con, const char *str, unsigned n)
+static void early_vga_write(struct console *con, const char *str, unsigned n,
+ unsigned int loglevel)
{
char c;
int i, k, j;
@@ -93,7 +94,8 @@ static int early_serial_putc(unsigned ch
return timeout ? 0 : -1;
}
-static void early_serial_write(struct console *con, const char *s, unsigned n)
+static void early_serial_write(struct console *con, const char *s, unsigned n,
+ unsigned int loglevel)
{
while (*s && n-- > 0) {
if (*s == '\n')
@@ -887,7 +889,7 @@ asmlinkage void early_printk(const char
va_start(ap, fmt);
n = vscnprintf(buf, sizeof(buf), fmt, ap);
- early_console->write(early_console, buf, n);
+ early_console->write(early_console, buf, n, 0);
va_end(ap);
}
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/drivers/char/Kconfig linux-2.6.29.3-cprintk/drivers/tty/Kconfig
--- a/drivers/char/Kconfig 2009-03-24 00:12:14.000000000 +0100
+++ b/drivers/tty/Kconfig 2009-05-09 14:43:48.000000000 +0200
@@ -66,6 +66,111 @@ config VT_CONSOLE
If unsure, say Y.
+menuconfig VT_CKO
+ bool "Colored kernel message output"
+ depends on VT_CONSOLE
+ ---help---
+ This option enables kernel messages to be emitted in
+ colors other than the default.
+
+ The color value you need to enter is composed (OR-ed)
+ of a foreground and a background color.
+
+ Foreground:
+ 0x00 = black, 0x08 = dark gray,
+ 0x01 = red, 0x09 = light red,
+ 0x02 = green, 0x0A = light green,
+ 0x03 = brown, 0x0B = yellow,
+ 0x04 = blue, 0x0C = light blue,
+ 0x05 = magenta, 0x0D = light magenta,
+ 0x06 = cyan, 0x0E = light cyan,
+ 0x07 = gray, 0x0F = white,
+
+ (Foreground colors 0x08 to 0x0F do not work when a VGA
+ console font with 512 glyphs is used.)
+
+ Background:
+ 0x00 = black, 0x40 = blue,
+ 0x10 = red, 0x50 = magenta,
+ 0x20 = green, 0x60 = cyan,
+ 0x30 = brown, 0x70 = gray,
+
+ For example, 0x1F would yield white on red.
+
+ If unsure, say N.
+
+config VT_PRINTK_EMERG_COLOR
+ hex "Emergency messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel emergency messages will
+ be printed to the console.
+
+config VT_PRINTK_ALERT_COLOR
+ hex "Alert messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel alert messages will
+ be printed to the console.
+
+config VT_PRINTK_CRIT_COLOR
+ hex "Critical messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel critical messages will
+ be printed to the console.
+
+config VT_PRINTK_ERR_COLOR
+ hex "Error messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel error messages will
+ be printed to the console.
+
+config VT_PRINTK_WARNING_COLOR
+ hex "Warning messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel warning messages will
+ be printed to the console.
+
+config VT_PRINTK_NOTICE_COLOR
+ hex "Notice messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel notice messages will
+ be printed to the console.
+
+config VT_PRINTK_INFO_COLOR
+ hex "Information messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel information messages will
+ be printed to the console.
+
+config VT_PRINTK_DEBUG_COLOR
+ hex "Debug messages color"
+ range 0x00 0xFF
+ depends on VT_CKO
+ default 0x07
+ ---help---
+ This option defines with which color kernel debug messages will
+ be printed to the console.
+
config HW_CONSOLE
bool
depends on VT && !S390 && !UML
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/drivers/char/vt.c linux-2.6.29.3-cprintk/drivers/tty/vt/vt.c
--- a/drivers/char/vt.c 2009-05-09 10:46:57.000000000 +0200
+++ b/drivers/tty/vt/vt.c 2009-05-09 14:43:48.000000000 +0200
@@ -73,6 +73,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/tty.h>
@@ -2431,17 +2432,45 @@ struct tty_driver *console_driver;
#ifdef CONFIG_VT_CONSOLE
+#ifdef CONFIG_VT_CKO
+static unsigned int printk_color[8] __read_mostly = {
+ CONFIG_VT_PRINTK_EMERG_COLOR, /* KERN_EMERG */
+ CONFIG_VT_PRINTK_ALERT_COLOR, /* KERN_ALERT */
+ CONFIG_VT_PRINTK_CRIT_COLOR, /* KERN_CRIT */
+ CONFIG_VT_PRINTK_ERR_COLOR, /* KERN_ERR */
+ CONFIG_VT_PRINTK_WARNING_COLOR, /* KERN_WARNING */
+ CONFIG_VT_PRINTK_NOTICE_COLOR, /* KERN_NOTICE */
+ CONFIG_VT_PRINTK_INFO_COLOR, /* KERN_INFO */
+ CONFIG_VT_PRINTK_DEBUG_COLOR, /* KERN_DEBUG */
+};
+module_param_array(printk_color, uint, NULL, S_IRUGO | S_IWUSR);
+
+static inline void vc_set_color(struct vc_data *vc, unsigned char color)
+{
+ vc->vc_color = color_table[color & 0xF] |
+ (color_table[(color >> 4) & 0x7] << 4) |
+ (color & 0x80);
+ update_attr(vc);
+}
+#else
+static unsigned int printk_color[8];
+static inline void vc_set_color(const struct vc_data *vc, unsigned char c)
+{
+}
+#endif
+
/*
* Console on virtual terminal
*
* The console must be locked when we get here.
*/
-static void vt_console_print(struct console *co, const char *b, unsigned count)
+static void vt_console_print(struct console *co, const char *b, unsigned count,
+ unsigned int loglevel)
{
struct vc_data *vc = vc_cons[fg_console].d;
- unsigned char c;
static DEFINE_SPINLOCK(printing_lock);
+ unsigned char current_color, c;
const ushort *start;
ushort cnt = 0;
ushort myx;
@@ -2474,11 +2503,19 @@ static void vt_console_print(struct cons
start = (ushort *)vc->vc_pos;
+ /*
+ * We always get a valid loglevel - <8> and "no level" is transformed
+ * to <4> in the typical kernel.
+ */
+ current_color = printk_color[loglevel];
+ vc_set_color(vc, current_color);
+
/* Contrived structure to try to emulate original need_wrap behaviour
* Problems caused when we have need_wrap set on '\n' character */
while (count--) {
c = *b++;
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
+ vc_set_color(vc, vc->vc_def_color);
if (cnt > 0) {
if (CON_IS_VISIBLE(vc))
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
@@ -2491,6 +2528,7 @@ static void vt_console_print(struct cons
bs(vc);
start = (ushort *)vc->vc_pos;
myx = vc->vc_x;
+ vc_set_color(vc, current_color);
continue;
}
if (c != 13)
@@ -2498,6 +2536,7 @@ static void vt_console_print(struct cons
cr(vc);
start = (ushort *)vc->vc_pos;
myx = vc->vc_x;
+ vc_set_color(vc, current_color);
if (c == 10 || c == 13)
continue;
}
@@ -2520,6 +2559,7 @@ static void vt_console_print(struct cons
vc->vc_need_wrap = 1;
}
}
+ vc_set_color(vc, vc->vc_def_color);
set_cursor(vc);
notify_update(vc);
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/drivers/net/netconsole.c linux-2.6.29.3-cprintk/drivers/net/netconsole.c
--- a/drivers/net/netconsole.c 2009-03-24 00:12:14.000000000 +0100
+++ b/drivers/net/netconsole.c 2009-05-09 14:43:48.000000000 +0200
@@ -691,7 +691,8 @@ static struct notifier_block netconsole_
.notifier_call = netconsole_netdev_event,
};
-static void write_msg(struct console *con, const char *msg, unsigned int len)
+static void write_msg(struct console *con, const char *msg, unsigned int len,
+ unsigned int loglevel)
{
int frag, left;
unsigned long flags;
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/drivers/serial/8250.c linux-2.6.29.3-cprintk/drivers/tty/serial/8250.c
--- a/drivers/serial/8250.c 2009-03-24 00:12:14.000000000 +0100
+++ b/drivers/tty/serial/8250.c 2009-05-09 14:43:48.000000000 +0200
@@ -2698,7 +2698,8 @@ static void serial8250_console_putchar(s
* The console_lock must be held when we get here.
*/
static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
+serial8250_console_write(struct console *co, const char *s, unsigned int count,
+ unsigned int loglevel)
{
struct uart_8250_port *up = &serial8250_ports[co->index];
unsigned long flags;
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/drivers/serial/8250_early.c linux-2.6.29.3-cprintk/drivers/tty/serial/8250_early.c
--- a/drivers/serial/8250_early.c 2009-03-24 00:12:14.000000000 +0100
+++ b/drivers/tty/serial/8250_early.c 2009-05-09 14:43:48.000000000 +0200
@@ -83,7 +83,7 @@ static void __init serial_putc(struct ua
}
static void __init early_serial8250_write(struct console *console,
- const char *s, unsigned int count)
+ const char *s, unsigned int count, unsigned int loglevel)
{
struct uart_port *port = &early_device.port;
unsigned int ier;
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/include/linux/console.h linux-2.6.29.3-cprintk/include/linux/console.h
--- a/include/linux/console.h 2009-03-24 00:12:14.000000000 +0100
+++ b/include/linux/console.h 2009-05-09 14:43:48.000000000 +0200
@@ -95,7 +95,7 @@ void give_up_console(const struct consw
struct console {
char name[16];
- void (*write)(struct console *, const char *, unsigned);
+ void (*write)(struct console *, const char *, unsigned, unsigned int);
int (*read)(struct console *, char *, unsigned);
struct tty_driver *(*device)(struct console *, int *);
void (*unblank)(void);
diff -pruN -X linux/Documentation/dontdiff linux-2.6.29.3/kernel/printk.c linux-2.6.29.3-cprintk/kernel/printk.c
--- a/kernel/printk.c 2009-03-24 00:12:14.000000000 +0100
+++ b/kernel/printk.c 2009-05-09 14:43:48.000000000 +0200
@@ -389,7 +389,8 @@ SYSCALL_DEFINE3(syslog, int, type, char
/*
* Call the console drivers on a range of log_buf
*/
-static void __call_console_drivers(unsigned start, unsigned end)
+static void __call_console_drivers(unsigned start, unsigned end,
+ unsigned int loglevel)
{
struct console *con;
@@ -397,7 +398,7 @@ static void __call_console_drivers(unsig
if ((con->flags & CON_ENABLED) && con->write &&
(cpu_online(smp_processor_id()) ||
(con->flags & CON_ANYTIME)))
- con->write(con, &LOG_BUF(start), end - start);
+ con->write(con, &LOG_BUF(start), end - start, loglevel);
}
}
@@ -424,10 +425,11 @@ static void _call_console_drivers(unsign
if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
/* wrapped write */
__call_console_drivers(start & LOG_BUF_MASK,
- log_buf_len);
- __call_console_drivers(0, end & LOG_BUF_MASK);
+ log_buf_len, msg_log_level);
+ __call_console_drivers(0, end & LOG_BUF_MASK,
+ msg_log_level);
} else {
- __call_console_drivers(start, end);
+ __call_console_drivers(start, end, msg_log_level);
}
}
}

View File

@ -0,0 +1,25 @@
diff -urN oldtree/kernel/Kconfig.hz newtree/kernel/Kconfig.hz
--- oldtree/kernel/Kconfig.hz 2007-03-06 15:00:55.000000000 -0500
+++ newtree/kernel/Kconfig.hz 2007-03-06 17:52:36.000000000 -0500
@@ -39,6 +39,14 @@
on SMP and NUMA systems and exactly dividing by both PAL and
NTSC frame rates for video and multimedia work.
+ config HZ_432
+ bool "432 HZ"
+ help
+ 432 HZ is the best value for desktop systems. Most responsive
+ out of all the options. This is for Dual Core/Processor systems only.
+ as timer frequencies * number of processors = actual frequency.
+ Try this if you have a dual-core/dual processor system.
+
config HZ_1000
bool "1000 HZ"
help
@@ -52,5 +60,6 @@
default 100 if HZ_100
default 250 if HZ_250_NODEFAULT
default 300 if HZ_300
+ default 432 if HZ_432
default 1000 if HZ_1000

View File

@ -0,0 +1,25 @@
diff -urN oldtree/kernel/Kconfig.hz newtree/kernel/Kconfig.hz
--- oldtree/kernel/Kconfig.hz 2007-03-06 15:00:55.000000000 -0500
+++ newtree/kernel/Kconfig.hz 2007-03-06 17:52:36.000000000 -0500
@@ -39,6 +39,14 @@
as timer frequencies * number of processors = actual frequency.
Try this if you have a dual-core/dual processor system.
+ config HZ_864
+ bool "864 HZ"
+ help
+ 864 HZ is the best value for desktop systems. Most responsive
+ out of all the options. The only reason it is not default is
+ because it may break few drivers. Give it a try if you have
+ a desktop :).
+
config HZ_1000
bool "1000 HZ"
help
@@ -52,5 +60,6 @@
default 250 if HZ_250_NODEFAULT
default 300 if HZ_300
default 432 if HZ_432
+ default 864 if HZ_864
default 1000 if HZ_1000

1603
3.2.34/imqmq-3.2.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
================================
Signed-off-by: Steve Brokenshire <sbrokenshire@xestia.co.uk>
[Rediffed for 2.6.31.3, defaulted to y and compress with -9 /Thomas]
Signed-off-by: Thomas Backlund <tmb@mandriva.org>
diff -Nurp linux-2.6.31/Documentation/kbuild/modules.txt linux-2.6.31.compress/Documentation/kbuild/modules.txt
--- linux-2.6.31/Documentation/kbuild/modules.txt 2009-09-10 01:13:59.000000000 +0300
+++ linux-2.6.31.compress/Documentation/kbuild/modules.txt 2009-10-09 14:17:49.335619817 +0300
@@ -123,6 +123,13 @@ executed to make module versioning work.
Install the external module(s). The default location is
/lib/modules/<kernel_release>/extra/, but a prefix may
be added with INSTALL_MOD_PATH (discussed in section 5).
+ If MODULES_COMPRESS is set when the modules_install target is
+ run then the module is compressed after it has been
+ copied to /lib/modules/<kernel-version>. Compressed modules
+ using the default gzip compression format will require
+ module-init-tools installed with --zlib-enabled.
+ Any options set in MODULE_COMPRESS_OPTIONS will be
+ passed to the selected compression format.
clean
Remove all generated files in the module directory only.
diff -Nurp linux-2.6.31/init/Kconfig linux-2.6.31.compress/init/Kconfig
--- linux-2.6.31/init/Kconfig 2009-09-10 01:13:59.000000000 +0300
+++ linux-2.6.31.compress/init/Kconfig 2009-10-09 14:19:01.812591181 +0300
@@ -1161,6 +1161,64 @@ config MODULE_FORCE_UNLOAD
rmmod). This is mainly for kernel developers and desperate users.
If unsure, say N.
+config MODULE_COMPRESS
+ bool "Compress kernel modules on installation"
+ depends on MODULES
+ default y
+ help
+ This option compresses the kernel modules when 'make
+ modules_install' is run.
+
+ The modules will be compressed into the selected compression
+ format with gzip being the default compression format.
+
+ When a kernel module is installed from outside of the main kernel
+ source and uses the Kbuild system for installing modules then that
+ kernel module will also be compressed when it is installed.
+
+ When running mkinitrd you will find that an error message
+ appears saying that it cannot find a certain kernel module.
+ As a workaround, unset CONFIG_MODULE_COMPRESS, build the modules
+ and install them, run mkinitrd and create the initrd image, place
+ the initrd image in the correct place for booting, set
+ CONFIG_MODULE_COMPRESS and then install the modules again.
+
+ This option requires the module-init-tools package to be
+ configured with --enable-zlib (if using gzip which is the
+ default compression format).
+
+ If unsure, say Y.
+
+config MODULE_COMPRESS_OPTIONS
+ string "Compression format command line options"
+ depends on MODULE_COMPRESS
+ default "-9"
+ help
+ This option specifies the command line options to be used for
+ the selected compression format.
+
+ Please refer to the selected compression format's documentation
+ on which options should be used.
+
+ If unsure, leave this option blank.
+
+choice
+ prompt "Kernel module compression format"
+ depends on MODULE_COMPRESS
+ default MODULE_COMPRESS_GZIP
+
+config MODULE_COMPRESS_GZIP
+ bool "gzip compression"
+ help
+ Compresses the kernel modules using the gzip (GNU zip)
+ compression format.
+
+ This option requires gzip to be installed.
+
+ If unsure, leave this option selected.
+
+endchoice
+
config MODVERSIONS
bool "Module versioning support"
help
diff -Nurp linux-2.6.31/scripts/Makefile.modinst linux-2.6.31.compress/scripts/Makefile.modinst
--- linux-2.6.31/scripts/Makefile.modinst 2009-09-10 01:13:59.000000000 +0300
+++ linux-2.6.31.compress/scripts/Makefile.modinst 2009-10-09 14:17:49.337619404 +0300
@@ -5,6 +5,7 @@
PHONY := __modinst
__modinst:
+include include/config/auto.conf
include scripts/Kbuild.include
#
@@ -16,8 +17,21 @@ PHONY += $(modules)
__modinst: $(modules)
@:
-quiet_cmd_modules_install = INSTALL $@
- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+ifeq ($(CONFIG_MODULE_COMPRESS_OPTIONS), "")
+else
+ MODCOMPOPT = $(shell echo -n $(CONFIG_MODULE_COMPRESS_OPTIONS))
+endif
+
+quiet_cmd_modules_install = INSTALL $@
+ cmd_modules_install = mkdir -p $(2); \
+ cp $@ $(2) ; \
+ $(mod_strip_cmd) $(2)/$(notdir $@)
+
+quiet_cmd_modules_compress_gzip = COMPRESS $@
+ cmd_modules_compress_gzip = gzip $(MODCOMPOPT) -c \
+ $(2)/$(@F) \
+ > $(2)/$(@F).gz; \
+ rm $(2)/$(@F)
# Modules built outside the kernel source tree go into extra by default
INSTALL_MOD_DIR ?= extra
@@ -26,8 +40,11 @@ ext-mod-dir = $(INSTALL_MOD_DIR)$(subst
modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D))
$(modules):
+
$(call cmd,modules_install,$(MODLIB)/$(modinst_dir))
+ $(if $(CONFIG_MODULE_COMPRESS_GZIP), \
+ $(call cmd,modules_compress_gzip,$(MODLIB)/$(modinst_dir)))
# Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable se we can use it in if_changed and friends.

View File

@ -0,0 +1,569 @@
diff -uprN linux-3.4-rc7/arch/arm/configs/orion5x_defconfig linux-3.4-rc7-wtgl/arch/arm/configs/orion5x_defconfig
--- linux-3.4-rc7/arch/arm/configs/orion5x_defconfig 2012-05-12 19:37:47.000000000 -0600
+++ linux-3.4-rc7-wtgl/arch/arm/configs/orion5x_defconfig 2012-08-16 23:41:47.118502384 -0600
@@ -19,6 +19,7 @@ CONFIG_MACH_TS209=y
CONFIG_MACH_TERASTATION_PRO2=y
CONFIG_MACH_LINKSTATION_PRO=y
CONFIG_MACH_LINKSTATION_MINI=y
+CONFIG_MACH_LINKSTATION_PRODUO=y
CONFIG_MACH_LINKSTATION_LS_HGL=y
CONFIG_MACH_TS409=y
CONFIG_MACH_WRT350N_V2=y
diff -uprN linux-3.4-rc7/arch/arm/mach-orion5x/Kconfig linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/Kconfig
--- linux-3.4-rc7/arch/arm/mach-orion5x/Kconfig 2012-05-12 19:37:47.000000000 -0600
+++ linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/Kconfig 2012-08-16 23:47:02.334496150 -0600
@@ -65,13 +65,52 @@ config MACH_LINKSTATION_MINI
Say 'Y' here if you want your kernel to support the
Buffalo Linkstation Mini platform.
+config MACH_LINKSTATION_PRODUO
+ bool "Buffalo Linkstation Pro Duo"
+ select I2C_BOARDINFO
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo Linkstation Pro Duo platform.
+
+ LS-W1.0TGL/R1 is the general model number. There
+ is no /R3 models, as /R1 stands for RAID1.
+ There are two hardware revisions of the product.
+
+ The first revision has version 1.xx firmware, 64 MB RAM,
+ a single USB port, a power BUTTON, an Auto/Manual
+ power MODE SWITCH, and a RESET button.
+
+ The second revision has version 3.xx firmware, 128 MB RAM,
+ two USB ports, an Off/On/Auto power SWITCH, and a FUNCTION button.
+
+ choice
+ prompt "HW model"
+ depends on MACH_LINKSTATION_PRODUO
+ default MACH_LINKSTATION_PRODUO_REV1
+ default MACH_LINKSTATION_PRODUO_REV2
+
+ config MACH_LINKSTATION_PRODUO_REV1
+ bool "Revision 1"
+ help
+ The first revision has version 1.xx firmware, 64 MB RAM,
+ a single USB port, a power BUTTON, an Auto/Manual
+ power MODE SWITCH, and a RESET button.
+
+ config MACH_LINKSTATION_PRODUO_REV2
+ bool "Revision 2"
+ help
+ The second revision has version 3.xx firmware, 128 MB RAM,
+ two USB ports, an Off/On/Auto power SWITCH, and a FUNCTION button.
+ endchoice
+
+
config MACH_LINKSTATION_LS_HGL
bool "Buffalo Linkstation LS-HGL"
select I2C_BOARDINFO
help
Say 'Y' here if you want your kernel to support the
Buffalo Linkstation LS-HGL platform.
-
+
config MACH_TS409
bool "QNAP TS-409"
help
diff -uprN linux-3.4-rc7/arch/arm/mach-orion5x/Makefile linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/Makefile
--- linux-3.4-rc7/arch/arm/mach-orion5x/Makefile 2012-05-12 19:37:47.000000000 -0600
+++ linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/Makefile 2012-08-16 23:48:26.182494492 -0600
@@ -5,6 +5,7 @@ obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobo
obj-$(CONFIG_MACH_TERASTATION_PRO2) += terastation_pro2-setup.o
obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o
obj-$(CONFIG_MACH_LINKSTATION_MINI) += lsmini-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_PRODUO) += lsproduo-setup.o
obj-$(CONFIG_MACH_LINKSTATION_LS_HGL) += ls_hgl-setup.o
obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
obj-$(CONFIG_MACH_TS209) += ts209-setup.o tsx09-common.o
diff -uprN linux-3.4-rc7/arch/arm/mach-orion5x/lsproduo-setup.c linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/lsproduo-setup.c
--- linux-3.4-rc7/arch/arm/mach-orion5x/lsproduo-setup.c 1969-12-31 17:00:00.000000000 -0700
+++ linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/lsproduo-setup.c 2012-08-16 23:52:09.630490073 -0600
@@ -0,0 +1,459 @@
+/*
+ * arch/arm/mach-orion5x/lsproduo-setup.c
+ *
+ * Source taken from arch/arm/mach-orion5x/lsmini-setup.c - kernel 2.6.30
+ * Maintainer: Matt Gomboc <gomboc0@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/orion5x.h>
+#include "common.h"
+#include "mpp.h"
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+/*****************************************************************************
+ * Linkstation Pro Duo Info
+ ****************************************************************************/
+
+/*
+ * 256K NOR flash Device bus boot chip select
+ */
+
+#define LSPRODUO_NOR_BOOT_BASE 0xf4000000
+#define LSPRODUO_NOR_BOOT_SIZE SZ_256K
+
+/*****************************************************************************
+ * 256KB NOR Flash on BOOT Device
+ ****************************************************************************/
+
+static struct physmap_flash_data lsproduo_nor_flash_data = {
+ .width = 1,
+};
+
+static struct resource lsproduo_nor_flash_resource = {
+ .flags = IORESOURCE_MEM,
+ .start = LSPRODUO_NOR_BOOT_BASE,
+ .end = LSPRODUO_NOR_BOOT_BASE + LSPRODUO_NOR_BOOT_SIZE - 1,
+};
+
+static struct platform_device lsproduo_nor_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &lsproduo_nor_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &lsproduo_nor_flash_resource,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data lsproduo_eth_data = {
+ .phy_addr = 8,
+};
+
+/*****************************************************************************
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+
+static struct i2c_board_info __initdata lsproduo_i2c_rtc = {
+ I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+
+#define LSPRODUO_GPIO_LED_ALARM 2
+#define LSPRODUO_GPIO_LED_INFO 3
+#define LSPRODUO_GPIO_LED_PWR 0
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+ #define LSPRODUO_GPIO_LED_FUNC 18
+#endif
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV1
+static struct gpio_led lsproduo_led_pins[] = {
+ {
+ .name = "alarm:red",
+ .gpio = LSPRODUO_GPIO_LED_ALARM,
+ .active_low = 1,
+ }, {
+ .name = "info:amber",
+ .gpio = LSPRODUO_GPIO_LED_INFO,
+ .active_low = 1,
+ }, {
+ .name = "power:greem",
+ .gpio = LSPRODUO_GPIO_LED_PWR,
+ .active_low = 1,
+ },
+};
+#endif
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+static struct gpio_led lsproduo_led_pins[] = {
+ {
+ .name = "alarm:red",
+ .gpio = LSPRODUO_GPIO_LED_ALARM,
+ .active_low = 1,
+ }, {
+ .name = "info:amber",
+ .gpio = LSPRODUO_GPIO_LED_INFO,
+ .active_low = 1,
+ }, {
+ .name = "power:green",
+ .gpio = LSPRODUO_GPIO_LED_PWR,
+ .active_low = 1,
+ },{
+ .name = "func:blue",
+ .gpio = LSPRODUO_GPIO_LED_FUNC,
+ .active_low = 1,
+ },
+};
+#endif
+
+
+
+static struct gpio_led_platform_data lsproduo_led_data = {
+ .leds = lsproduo_led_pins,
+ .num_leds = ARRAY_SIZE(lsproduo_led_pins),
+};
+
+static struct platform_device lsproduo_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lsproduo_led_data,
+ },
+};
+
+/****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV1
+ #define LSPRODUO_GPIO_KEY_POWER 8
+ #define LSPRODUO_GPIO_KEY_AUTOPOWER 10
+
+ #define LSPRODUO_SW_POWER 0x00
+ #define LSPRODUO_SW_AUTOPOWER 0x01
+
+static struct gpio_keys_button lsproduo_buttons[] = {
+ {
+ .type = EV_SW,
+ .code = LSPRODUO_SW_POWER,
+ .gpio = LSPRODUO_GPIO_KEY_POWER,
+ .desc = "Power-on Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSPRODUO_SW_AUTOPOWER,
+ .gpio = LSPRODUO_GPIO_KEY_AUTOPOWER,
+ .desc = "Power-auto Switch",
+ .active_low = 1,
+ },
+};
+
+#endif
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+ #define LSPRODUO_GPIO_KEY_POWER 10
+ #define LSPRODUO_GPIO_KEY_AUTOPOWER 22
+ #define LSPRODUO_GPIO_KEY_FUNC 8
+
+ #define LSPRODUO_SW_POWER 0x00
+ #define LSPRODUO_SW_AUTOPOWER 0x01
+
+static struct gpio_keys_button lsproduo_buttons[] = {
+ {
+ .code = KEY_OPTION,
+ .gpio = LSPRODUO_GPIO_KEY_FUNC,
+ .desc = "Function Button",
+ .active_low = 1,
+ },{
+ .type = EV_SW,
+ .code = LSPRODUO_SW_POWER,
+ .gpio = LSPRODUO_GPIO_KEY_POWER,
+ .desc = "Power-on Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSPRODUO_SW_AUTOPOWER,
+ .gpio = LSPRODUO_GPIO_KEY_AUTOPOWER,
+ .desc = "Power-auto Switch",
+ .active_low = 1,
+ },
+};
+
+#endif
+
+static struct gpio_keys_platform_data lsproduo_button_data = {
+ .buttons = lsproduo_buttons,
+ .nbuttons = ARRAY_SIZE(lsproduo_buttons),
+};
+
+static struct platform_device lsproduo_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsproduo_button_data,
+ },
+};
+
+/****************************************************************************
+ * GPIO Attached Fan
+ ****************************************************************************/
+
+/* Define max char len */
+#define MAX_LEN 8
+
+#define LSPRODUO_GPIO_FAN_LOW 17
+#define LSPRODUO_GPIO_FAN_HIGH 14
+
+static struct proc_dir_entry *lsproduo_proc_dir_root, *lsproduo_proc_dir_gpio, *lsproduo_fan_proc_file;
+static char lsproduo_fan_state[MAX_LEN];
+
+static int lsproduo_fan_get(char *buf, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int len;
+
+ len = snprintf(buf, count, "state: %s\n", lsproduo_fan_state);
+ return len;
+}
+
+static int lsproduo_fan_set( struct file *file, const char *buffer, unsigned long count, void *data )
+{
+ int len, ret;
+ char *ptr, tState[MAX_LEN];
+
+ if (count > MAX_LEN )
+ len = MAX_LEN;
+ else
+ len = count;
+
+ ret = copy_from_user(tState, buffer, len);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: Setting fan speed failed\n", "lsproduo");
+ return -EFAULT;
+ }
+
+ ptr = strrchr(tState, '\n');
+ if(ptr) *ptr = '\0';
+
+ if (strcasecmp(tState, "off") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan off\n", "lsproduo");
+ sprintf(lsproduo_fan_state, "off");
+ gpio_set_value(LSPRODUO_GPIO_FAN_LOW, 1);
+ gpio_set_value(LSPRODUO_GPIO_FAN_HIGH, 1);
+ } else if (strcasecmp(tState, "slow") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan slow\n", "lsproduo");
+ sprintf(lsproduo_fan_state, "slow");
+ gpio_set_value(LSPRODUO_GPIO_FAN_LOW, 1);
+ gpio_set_value(LSPRODUO_GPIO_FAN_HIGH, 0);
+ } else if (strcasecmp(tState, "fast") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan fast\n", "lsproduo");
+ sprintf(lsproduo_fan_state, "fast");
+ gpio_set_value(LSPRODUO_GPIO_FAN_LOW, 0);
+ gpio_set_value(LSPRODUO_GPIO_FAN_HIGH, 1);
+ } else if (strcasecmp(tState, "full") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan full\n", "lsproduo");
+ sprintf(lsproduo_fan_state, "full");
+ gpio_set_value(LSPRODUO_GPIO_FAN_LOW, 0);
+ gpio_set_value(LSPRODUO_GPIO_FAN_HIGH, 0);
+ } else
+ {
+ printk(KERN_ERR "%s: unknown fan speed given\n", "lsproduo");
+ }
+
+ lsproduo_fan_state[len] = '\0';
+
+ return len;
+}
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lsproduo_sata_data = {
+ .n_ports = 2,
+};
+
+
+/*****************************************************************************
+ * Linkstation Pro Duo specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the Linkstation Pro Duo, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ */
+
+static void lsproduo_power_off(void)
+{
+ /* orion5x_restart('h', NULL); */
+ arm_machine_restart(0, NULL);
+}
+
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSPRODUO_GPIO_HDD_POWER0 1
+#define LSPRODUO_GPIO_USB_POWER 9
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV1
+ #define LSPRODUO_GPIO_POWER 8
+ #define LSPRODUO_GPIO_AUTO_POWER 10
+#endif
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+ #define LSPRODUO_GPIO_POWER 10
+ #define LSPRODUO_GPIO_USB_POWER2 19
+ #define LSPRODUO_GPIO_AUTO_POWER 22
+#endif
+
+static unsigned int lsproduo_mpp_modes[] __initdata = {
+ MPP0_GPIO, /* LED_PWR */
+ MPP1_GPIO, /* HDD_PWR */
+ MPP2_GPIO, /* LED_ALARM */
+ MPP3_GPIO, /* LED_INFO */
+ MPP4_UNUSED,
+ MPP5_UNUSED,
+ MPP6_GPIO, /* FAN_LCK */
+ MPP9_GPIO, /* USB_PWR */
+ MPP11_UNUSED, /* LED_ETH dummy */
+ MPP12_UNUSED,
+ MPP13_UNUSED,
+ MPP14_GPIO, /* FAN_HIGH */
+ MPP15_UNUSED,
+ MPP16_UNUSED,
+ MPP17_GPIO, /* FAN_LOW */
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV1
+ MPP7_GPIO, /* INIT */
+ MPP8_GPIO, /* POWER */
+ MPP10_GPIO, /* AUTO_POWER */
+ MPP18_UNUSED,
+ MPP19_UNUSED,
+#endif
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+ MPP7_UNUSED,
+ MPP8_GPIO, /* FUNC */
+ MPP10_GPIO, /* POWER */
+ MPP18_GPIO, /* LED_FUNC*/
+ MPP19_GPIO, /* USB_PWR2 */
+ MPP22_GPIO, /* AUTO_POWER */
+#endif
+ 0,
+};
+
+static void __init lsproduo_init(void)
+{
+ /*
+ * Setup basic Orion functions. Need to be called early.
+ */
+ orion5x_init();
+
+ orion5x_mpp_conf(lsproduo_mpp_modes);
+
+ /*
+ * Configure peripherals.
+ */
+ orion5x_ehci0_init();
+ orion5x_ehci1_init();
+ orion5x_eth_init(&lsproduo_eth_data);
+ orion5x_i2c_init();
+ orion5x_sata_init(&lsproduo_sata_data);
+ orion5x_uart0_init();
+ orion5x_xor_init();
+
+ orion5x_setup_dev_boot_win(LSPRODUO_NOR_BOOT_BASE,
+ LSPRODUO_NOR_BOOT_SIZE);
+ platform_device_register(&lsproduo_nor_flash);
+
+ platform_device_register(&lsproduo_button_device);
+
+ platform_device_register(&lsproduo_leds);
+
+ i2c_register_board_info(0, &lsproduo_i2c_rtc, 1);
+
+ /* enable USB power */
+ gpio_set_value(LSPRODUO_GPIO_USB_POWER, 1);
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+ gpio_set_value(LSPRODUO_GPIO_USB_POWER2, 1);
+#endif
+
+ printk(KERN_INFO "Buffalo Linkstation Pro Duo fan driver loaded\n");
+ sprintf(lsproduo_fan_state, "fast");
+ gpio_set_value(LSPRODUO_GPIO_FAN_LOW, 1);
+ gpio_set_value(LSPRODUO_GPIO_FAN_HIGH, 0);
+
+ lsproduo_proc_dir_root = proc_mkdir( "linkstation", NULL );
+ lsproduo_proc_dir_gpio = proc_mkdir( "gpio", lsproduo_proc_dir_root );
+ lsproduo_fan_proc_file = create_proc_entry( "fan", S_IRUGO, lsproduo_proc_dir_gpio );
+ if( lsproduo_fan_proc_file ) {
+ lsproduo_fan_proc_file->read_proc = lsproduo_fan_get;
+ lsproduo_fan_proc_file->write_proc = lsproduo_fan_set;
+ lsproduo_fan_proc_file->data = NULL;
+ } else
+ {
+ printk(KERN_INFO "Registration of fan device failed\n");
+ }
+
+ /* register power-off method */
+ pm_power_off = lsproduo_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV1
+MACHINE_START(LINKSTATION_PRODUO, "Buffalo Linkstation Pro Duo - Revision 1")
+ .atag_offset = 0x00000100,
+ .init_machine = lsproduo_init,
+ .map_io = orion5x_map_io,
+ .init_early = orion5x_init_early,
+ .init_irq = orion5x_init_irq,
+ .timer = &orion5x_timer,
+ .fixup = tag_fixup_mem32,
+ /* .restart = orion5x_restart, */
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_LINKSTATION_PRODUO_REV2
+MACHINE_START(LINKSTATION_PRODUO, "Buffalo Linkstation Pro Duo - Revision 2")
+ .atag_offset = 0x00000100,
+ .init_machine = lsproduo_init,
+ .map_io = orion5x_map_io,
+ .init_early = orion5x_init_early,
+ .init_irq = orion5x_init_irq,
+ .timer = &orion5x_timer,
+ .fixup = tag_fixup_mem32,
+ /* .restart = orion5x_restart, */
+MACHINE_END
+#endif
+
+
+
diff -uprN linux-3.4-rc7/arch/arm/mach-orion5x/mpp.h linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/mpp.h
--- linux-3.4-rc7/arch/arm/mach-orion5x/mpp.h 2012-05-12 19:37:47.000000000 -0600
+++ linux-3.4-rc7-wtgl/arch/arm/mach-orion5x/mpp.h 2012-08-16 22:15:34.000000000 -0600
@@ -122,7 +122,10 @@
#define MPP19_GIGE MPP(19, 0x1, 0, 0, 1, 1, 1)
#define MPP19_UART MPP(19, 0x0, 0, 0, 0, 1, 1)
-#define MPP_MAX 19
+#define MPP22_GPIO MPP(22, 0x5, 1, 1, 0, 1, 0)
+
+
+#define MPP_MAX 22
void orion5x_mpp_conf(unsigned int *mpp_list);
diff -uprN linux-3.4-rc7/arch/arm/tools/mach-types linux-3.4-rc7-wtgl/arch/arm/tools/mach-types
--- linux-3.4-rc7/arch/arm/tools/mach-types 2012-05-12 19:37:47.000000000 -0600
+++ linux-3.4-rc7-wtgl/arch/arm/tools/mach-types 2012-08-16 23:43:59.830499760 -0600
@@ -333,6 +333,8 @@ smdkc100 MACH_SMDKC100 SMDKC100 1826
tavorevb MACH_TAVOREVB TAVOREVB 1827
saar MACH_SAAR SAAR 1828
at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830
+linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
+##see header for btaining a new version, preferred to patching
usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841
mxlads MACH_MXLADS MXLADS 1851
linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858

View File

@ -0,0 +1,439 @@
diff -uNr linux-3.2.33-go.orig/arch/arm/configs/orion5x_defconfig linux-3.2.33-go/arch/arm/configs/orion5x_defconfig
--- linux-3.2.33-go.orig/arch/arm/configs/orion5x_defconfig 2012-11-11 15:13:23.313493927 +0100
+++ linux-3.2.33-go/arch/arm/configs/orion5x_defconfig 2012-11-11 15:14:01.321037277 +0100
@@ -21,6 +21,7 @@
CONFIG_MACH_LINKSTATION_MINI=y
CONFIG_MACH_LINKSTATION_PRODUO=y
CONFIG_MACH_LINKSTATION_LS_HGL=y
+CONFIG_MACH_LINKSTATION_LSQL=y
CONFIG_MACH_TS409=y
CONFIG_MACH_WRT350N_V2=y
CONFIG_MACH_TS78XX=y
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-orion5x/Kconfig linux-3.2.33-go/arch/arm/mach-orion5x/Kconfig
--- linux-3.2.33-go.orig/arch/arm/mach-orion5x/Kconfig 2012-11-11 15:13:23.518491566 +0100
+++ linux-3.2.33-go/arch/arm/mach-orion5x/Kconfig 2012-11-11 15:14:01.321037277 +0100
@@ -111,6 +111,13 @@
Say 'Y' here if you want your kernel to support the
Buffalo Linkstation LS-HGL platform.
+config MACH_LINKSTATION_LSQL
+ bool "Buffalo Linkstation LS-QL"
+ select I2C_BOARDINFO
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo Linkstation LS-QL platform.
+
config MACH_TS409
bool "QNAP TS-409"
help
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-orion5x/lsql-setup.c linux-3.2.33-go/arch/arm/mach-orion5x/lsql-setup.c
--- linux-3.2.33-go.orig/arch/arm/mach-orion5x/lsql-setup.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.2.33-go/arch/arm/mach-orion5x/lsql-setup.c 2012-11-11 15:14:01.323037254 +0100
@@ -0,0 +1,388 @@
+/*
+ * arch/arm/mach-orion5x/lsql-setup.c
+ *
+ * Source based off arch/arm/mach-orion5x/lsproduo-setup.c, which was from lsmini-setup.c
+ * Maintainer: Matt Gomboc <gomboc0@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/orion5x.h>
+#include "common.h"
+#include "mpp.h"
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+/*****************************************************************************
+ * Linkstation Quad LS-QL/R5 Info
+ ****************************************************************************/
+
+/*
+ * 256K NOR flash Device bus boot chip select
+ */
+
+#define LSQL_NOR_BOOT_BASE 0xf4000000
+#define LSQL_NOR_BOOT_SIZE SZ_256K
+
+/*****************************************************************************
+ * 256KB NOR Flash on BOOT Device
+ ****************************************************************************/
+
+static struct physmap_flash_data lsql_nor_flash_data = {
+ .width = 1,
+};
+
+static struct resource lsql_nor_flash_resource = {
+ .flags = IORESOURCE_MEM,
+ .start = LSQL_NOR_BOOT_BASE,
+ .end = LSQL_NOR_BOOT_BASE + LSQL_NOR_BOOT_SIZE - 1,
+};
+
+static struct platform_device lsql_nor_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &lsql_nor_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &lsql_nor_flash_resource,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data lsql_eth_data = {
+ .phy_addr = 8,
+};
+
+/*****************************************************************************
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+
+static struct i2c_board_info __initdata lsql_i2c_rtc = {
+ I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+
+#define LSQL_GPIO_LED_ALARM 2 /* looks like it should be 2 by the uboot sources, but doesnt successfully trigger the3 top LED*/
+#define LSQL_GPIO_LED_INFO 3
+#define LSQL_GPIO_LED_PWR 0
+#define LSQL_GPIO_LED_FUNC 18
+
+
+static struct gpio_led lsql_led_pins[] = {
+ {
+ .name = "alarm:red",
+ .gpio = LSQL_GPIO_LED_ALARM,
+ .active_low = 1,
+ }, {
+ .name = "info:amber",
+ .gpio = LSQL_GPIO_LED_INFO,
+ .active_low = 1,
+ }, {
+ .name = "power:blue",
+ .gpio = LSQL_GPIO_LED_PWR,
+ .active_low = 1,
+ },{
+ .name = "func:blue",
+ .gpio = LSQL_GPIO_LED_FUNC,
+ .active_low = 1,
+ },
+};
+
+
+
+static struct gpio_led_platform_data lsql_led_data = {
+ .leds = lsql_led_pins,
+ .num_leds = ARRAY_SIZE(lsql_led_pins),
+};
+
+
+static struct platform_device lsql_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lsql_led_data,
+ },
+};
+
+
+/****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+
+ #define LSQL_GPIO_KEY_POWER 10
+ #define LSQL_GPIO_KEY_AUTOPOWER 22
+ #define LSQL_GPIO_KEY_FUNC 7
+
+ #define LSQL_SW_POWER 0x00
+ #define LSQL_SW_AUTOPOWER 0x01
+
+static struct gpio_keys_button lsql_buttons[] = {
+ {
+ .code = KEY_OPTION,
+ .gpio = LSQL_GPIO_KEY_FUNC,
+ .desc = "Function Button",
+ .active_low = 1,
+ },{
+ .type = EV_SW,
+ .code = LSQL_SW_POWER,
+ .gpio = LSQL_GPIO_KEY_POWER,
+ .desc = "Power-on Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSQL_SW_AUTOPOWER,
+ .gpio = LSQL_GPIO_KEY_AUTOPOWER,
+ .desc = "Power-auto Switch",
+ .active_low = 1,
+ },
+};
+
+
+static struct gpio_keys_platform_data lsql_button_data = {
+ .buttons = lsql_buttons,
+ .nbuttons = ARRAY_SIZE(lsql_buttons),
+};
+
+static struct platform_device lsql_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsql_button_data,
+ },
+};
+
+/****************************************************************************
+ * GPIO Attached Fan
+ ****************************************************************************/
+
+/* Define max char len */
+
+#define MAX_LEN 8
+
+#define LSQL_GPIO_FAN_LOW 17
+#define LSQL_GPIO_FAN_HIGH 14
+
+static struct proc_dir_entry *lsql_proc_dir_root, *lsql_proc_dir_gpio, *lsql_fan_proc_file;
+static char lsql_fan_state[MAX_LEN];
+
+static int lsql_fan_get(char *buf, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int len;
+
+ len = snprintf(buf, count, "state: %s\n", lsql_fan_state);
+ return len;
+}
+
+static int lsql_fan_set( struct file *file, const char *buffer, unsigned long count, void *data )
+{
+ int len, ret;
+ char *ptr, tState[MAX_LEN];
+
+ if (count > MAX_LEN )
+ len = MAX_LEN;
+ else
+ len = count;
+
+ ret = copy_from_user(tState, buffer, len);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: Setting fan speed failed\n", "lsql");
+ return -EFAULT;
+ }
+
+ ptr = strrchr(tState, '\n');
+ if(ptr) *ptr = '\0';
+
+ if (strcasecmp(tState, "off") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan off\n", "lsql");
+ sprintf(lsql_fan_state, "off");
+ gpio_set_value(LSQL_GPIO_FAN_LOW, 1);
+ gpio_set_value(LSQL_GPIO_FAN_HIGH, 1);
+ } else if (strcasecmp(tState, "slow") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan slow\n", "lsql");
+ sprintf(lsql_fan_state, "slow");
+ gpio_set_value(LSQL_GPIO_FAN_LOW, 1);
+ gpio_set_value(LSQL_GPIO_FAN_HIGH, 0);
+ } else if (strcasecmp(tState, "fast") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan fast\n", "lsql");
+ sprintf(lsql_fan_state, "fast");
+ gpio_set_value(LSQL_GPIO_FAN_LOW, 0);
+ gpio_set_value(LSQL_GPIO_FAN_HIGH, 1);
+ } else if (strcasecmp(tState, "full") == 0)
+ {
+ printk(KERN_DEBUG "%s: set fan full\n", "lsql");
+ sprintf(lsql_fan_state, "full");
+ gpio_set_value(LSQL_GPIO_FAN_LOW, 0);
+ gpio_set_value(LSQL_GPIO_FAN_HIGH, 0);
+ } else
+ {
+ printk(KERN_ERR "%s: unknown fan speed given\n", "lsql");
+ }
+
+ lsql_fan_state[len] = '\0';
+
+ return len;
+}
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lsql_sata_data = {
+ .n_ports = 2, /*maybe this should be 4, but works with 2 */
+};
+
+
+/*****************************************************************************
+ * Linkstation Quad specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On Linkstations in general, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ *
+ * on the Quad however, there is a power button on the upper, front,
+ * a function button on the lower front, ans a Auto/Manual power button on the back.
+ * After halting system, uboot waits the power button on the front panel to be pushed
+ *
+ *
+ */
+
+static void lsql_power_off(void)
+{
+ arm_machine_restart(0, NULL); /* orion5x_restart('h', NULL); */
+}
+
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSQL_GPIO_USB_POWER 9
+#define LSQL_GPIO_POWER 10
+#define LSQL_GPIO_USB_POWER2 19
+#define LSQL_GPIO_AUTO_POWER 22
+
+static unsigned int lsql_mpp_modes[] __initdata = {
+ MPP0_GPIO, /* LED_PWR */
+ MPP1_GPIO, /* for debugging purposes, change to MPP1_UNUSED for final */
+ MPP2_GPIO, /* LED_ALARM */ /* looks like it should be 2 by the uboot sources, but doesnt successfully trigger the3 top LED*/
+ MPP3_GPIO, /* LED_INFO */
+ MPP4_GPIO,
+ MPP5_GPIO,
+ MPP6_GPIO, /* FAN_LCK */
+ MPP7_GPIO, /* FUNC */
+ MPP8_GPIO,
+ MPP9_GPIO, /* USB_PWR */
+ MPP10_GPIO, /* POWER */
+ MPP11_GPIO,
+ MPP12_GPIO,
+ MPP13_GPIO,
+ MPP14_GPIO, /* FAN_HIGH */
+ MPP15_GPIO,
+ MPP16_GPIO,
+ MPP17_GPIO, /* FAN_LOW */
+ MPP18_GPIO, /* LED_FUNC*/
+ MPP19_GPIO, /* USB_PWR2 */
+ MPP22_GPIO, /* AUTO_POWER*/
+ 0,
+};
+
+static void __init lsql_init(void)
+{
+ /*
+ * Setup basic Orion functions. Need to be called early.
+ */
+ orion5x_init();
+
+ orion5x_mpp_conf(lsql_mpp_modes);
+
+ /*
+ * Configure peripherals.
+ */
+ orion5x_ehci0_init();
+ orion5x_ehci1_init();
+ orion5x_eth_init(&lsql_eth_data);
+ orion5x_i2c_init();
+ orion5x_sata_init(&lsql_sata_data);
+ orion5x_uart0_init();
+ orion5x_xor_init();
+
+ orion5x_setup_dev_boot_win(LSQL_NOR_BOOT_BASE,
+ LSQL_NOR_BOOT_SIZE);
+ platform_device_register(&lsql_nor_flash);
+
+ platform_device_register(&lsql_button_device);
+
+ platform_device_register(&lsql_leds);
+
+ i2c_register_board_info(0, &lsql_i2c_rtc, 1);
+
+ /* enable USB power */
+ gpio_set_value(LSQL_GPIO_USB_POWER, 1);
+ gpio_set_value(LSQL_GPIO_USB_POWER2, 1);
+
+
+ printk(KERN_INFO "Buffalo Linkstation fan driver loaded\n");
+ sprintf(lsql_fan_state, "fast");
+ gpio_set_value(LSQL_GPIO_FAN_LOW, 0);
+ gpio_set_value(LSQL_GPIO_FAN_HIGH, 1);
+
+ lsql_proc_dir_root = proc_mkdir( "linkstation", NULL );
+ lsql_proc_dir_gpio = proc_mkdir( "gpio", lsql_proc_dir_root );
+ lsql_fan_proc_file = create_proc_entry( "fan", S_IRUGO, lsql_proc_dir_gpio );
+ if( lsql_fan_proc_file ) {
+ lsql_fan_proc_file->read_proc = lsql_fan_get;
+ lsql_fan_proc_file->write_proc = lsql_fan_set;
+ lsql_fan_proc_file->data = NULL;
+ } else
+ {
+ printk(KERN_INFO "Registration of fan device failed\n");
+ }
+
+ /* register power-off method */
+ pm_power_off = lsql_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+#ifdef CONFIG_MACH_LINKSTATION_LSQL
+MACHINE_START(LINKSTATION_LSQL, "Buffalo Linkstation Quad QL/R5")
+ .atag_offset = 0x00000100,
+ .init_machine = lsql_init,
+ .map_io = orion5x_map_io,
+ .init_early = orion5x_init_early,
+ .init_irq = orion5x_init_irq,
+ .timer = &orion5x_timer,
+ .fixup = tag_fixup_mem32,
+ /* .restart = orion5x_restart, */
+MACHINE_END
+#endif
+
+
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-orion5x/Makefile linux-3.2.33-go/arch/arm/mach-orion5x/Makefile
--- linux-3.2.33-go.orig/arch/arm/mach-orion5x/Makefile 2012-11-11 15:13:23.517491578 +0100
+++ linux-3.2.33-go/arch/arm/mach-orion5x/Makefile 2012-11-11 15:14:01.323037254 +0100
@@ -7,6 +7,7 @@
obj-$(CONFIG_MACH_LINKSTATION_MINI) += lsmini-setup.o
obj-$(CONFIG_MACH_LINKSTATION_PRODUO) += lsproduo-setup.o
obj-$(CONFIG_MACH_LINKSTATION_LS_HGL) += ls_hgl-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_LSQL) += lsql-setup.o
obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
obj-$(CONFIG_MACH_TS209) += ts209-setup.o tsx09-common.o
obj-$(CONFIG_MACH_TS409) += ts409-setup.o tsx09-common.o
diff -uNr linux-3.2.33-go.orig/arch/arm/tools/mach-types linux-3.2.33-go/arch/arm/tools/mach-types
--- linux-3.2.33-go.orig/arch/arm/tools/mach-types 2012-11-11 15:13:23.340493615 +0100
+++ linux-3.2.33-go/arch/arm/tools/mach-types 2012-11-11 15:14:26.618733715 +0100
@@ -1129,3 +1129,4 @@
m28evk MACH_M28EVK M28EVK 3613
smdk4212 MACH_SMDK4212 SMDK4212 3638
smdk4412 MACH_SMDK4412 SMDK4412 3765
+linkstation_lsql MACH_LINKSTATION_LSQL LINKSTATION_LSQL 4238

View File

@ -0,0 +1,387 @@
Add support for the Buffalo Linkstation XHL. This NAS box is based on a
Marvell Kirkwood chip at 1.2 GHz and features 256 MB RAM, 512kb SPI boot
flash, gigabit ethernet and one SATA port.
Signed-off-by: Michael Walle <michael at walle.cc>
---
arch/arm/configs/kirkwood_defconfig | 1 +
arch/arm/mach-kirkwood/Kconfig | 6 +
arch/arm/mach-kirkwood/Makefile | 1 +
arch/arm/mach-kirkwood/lsxhl-setup.c | 313 ++++++++++++++++++++++++++++++++++
arch/arm/tools/mach-types | 1 +
5 files changed, 322 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-kirkwood/lsxhl-setup.c
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index aeb3af5..9f77811 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -28,6 +28,7 @@ CONFIG_MACH_D2NET_V2=y
CONFIG_MACH_NET2BIG_V2=y
CONFIG_MACH_NET5BIG_V2=y
CONFIG_MACH_T5325=y
+CONFIG_MACH_LSXHL=y
# CONFIG_CPU_FEROCEON_OLD_ID is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 7fc603b..307cc99 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -130,6 +130,12 @@ config MACH_T5325
Say 'Y' here if you want your kernel to support the
HP t5325 Thin Client.
+config MACH_LSXHL
+ bool "Buffalo LS-XHL Series"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo LS-XHL Series.
+
endmenu
endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 5dcaa81..221980b 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -18,5 +18,6 @@ obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o
obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
obj-$(CONFIG_MACH_T5325) += t5325-setup.o
+obj-$(CONFIG_MACH_LSXHL) += lsxhl-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff --git a/arch/arm/mach-kirkwood/lsxhl-setup.c b/arch/arm/mach-kirkwood/lsxhl-setup.c
new file mode 100644
index 0000000..783d257
--- /dev/null
+++ b/arch/arm/mach-kirkwood/lsxhl-setup.c
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-kirkwood/lsxhl-setup.c
+ *
+ * Buffalo LS-XHL Series Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/ata_platform.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on BOOT Device
+ ****************************************************************************/
+static struct mtd_partition lsxhl_partitions[] = {
+ {
+ .name = "u-boot",
+ .size = 0x70000,
+ .offset = 0x00000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot env",
+ .size = 0x10000,
+ .offset = 0x70000,
+ }
+};
+
+static struct flash_platform_data lsxhl_spi_slave_data = {
+ .type = "m25p40",
+ .parts = lsxhl_partitions,
+ .nr_parts = ARRAY_SIZE(lsxhl_partitions),
+};
+
+static struct spi_board_info __initdata lsxhl_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lsxhl_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ }
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+static struct mv643xx_eth_platform_data lsxhl_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv643xx_eth_platform_data lsxhl_ge01_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lsxhl_sata_data = {
+ .n_ports = 1,
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+#define LSXHL_GPIO_LED_ALARM 37
+#define LSXHL_GPIO_LED_INFO 38
+#define LSXHL_GPIO_LED_PWR 39
+#define LSXHL_GPIO_LED_FUNC_BLUE 36
+#define LSXHL_GPIO_LED_FUNC_RED 48
+
+static struct gpio_led lsxhl_led_pins[] = {
+ {
+ .name = "alarm:red",
+ .gpio = LSXHL_GPIO_LED_ALARM,
+ .active_low = 1,
+ },
+ {
+ .name = "info:amber",
+ .gpio = LSXHL_GPIO_LED_INFO,
+ .active_low = 1,
+ },
+ {
+ .name = "power:blue",
+ .default_trigger = "default-on",
+ .gpio = LSXHL_GPIO_LED_PWR,
+ .active_low = 1,
+ },
+ {
+ .name = "func:blue:bottom",
+ .gpio = LSXHL_GPIO_LED_FUNC_BLUE,
+ .active_low = 1,
+ },
+ {
+ .name = "func:red:bottom",
+ .gpio = LSXHL_GPIO_LED_FUNC_RED,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data lsxhl_led_data = {
+ .leds = lsxhl_led_pins,
+ .num_leds = ARRAY_SIZE(lsxhl_led_pins),
+};
+
+static struct platform_device lsxhl_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lsxhl_led_data,
+ }
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSXHL_GPIO_HDD_POWER 10
+#define LSXHL_GPIO_USB_POWER 11
+
+/*****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LSXHL_GPIO_KEY_FUNC 41
+#define LSXHL_GPIO_KEY_AUTOPOWER 42
+#define LSXHL_GPIO_KEY_POWER 43
+#define LSXHL_SW_POWER 0x00
+#define LSXHL_SW_AUTOPOWER 0x01
+#define LSXHL_SW_FUNC 0x02
+
+static struct gpio_keys_button lsxhl_buttons[] = {
+ {
+ .type = EV_SW,
+ .code = LSXHL_SW_POWER,
+ .gpio = LSXHL_GPIO_KEY_POWER,
+ .desc = "Power-on Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSXHL_SW_AUTOPOWER,
+ .gpio = LSXHL_GPIO_KEY_AUTOPOWER,
+ .desc = "Power-auto Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSXHL_SW_POWER,
+ .gpio = LSXHL_GPIO_KEY_FUNC,
+ .desc = "Function Button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data lsxhl_button_data = {
+ .buttons = lsxhl_buttons,
+ .nbuttons = ARRAY_SIZE(lsxhl_buttons),
+};
+
+static struct platform_device lsxhl_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsxhl_button_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+#define LSXHL_GPIO_FAN_HIGH 18
+#define LSXHL_GPIO_FAN_LOW 19
+#define LSXHL_GPIO_FAN_LOCK 40
+
+static struct gpio_fan_alarm lsxhl_alarm = {
+ .gpio = LSXHL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lsxhl_speeds[] = {
+ {
+ .rpm = 0,
+ .ctrl_val = 3,
+ }, {
+ .rpm = 1500,
+ .ctrl_val = 1,
+ }, {
+ .rpm = 3250,
+ .ctrl_val = 2,
+ }, {
+ .rpm = 5000,
+ .ctrl_val = 0,
+ }
+};
+
+static int lsxhl_gpio_list[] = {
+ LSXHL_GPIO_FAN_HIGH, LSXHL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lsxhl_fan_data = {
+ .num_ctrl = ARRAY_SIZE(lsxhl_gpio_list),
+ .ctrl = lsxhl_gpio_list,
+ .alarm = &lsxhl_alarm,
+ .num_speed = ARRAY_SIZE(lsxhl_speeds),
+ .speed = lsxhl_speeds,
+};
+
+static struct platform_device lsxhl_fan_device = {
+ .name = "gpio-fan",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsxhl_fan_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static unsigned int lsxhl_mpp_config[] __initdata = {
+ MPP10_GPO, /* HDD Power Enable */
+ MPP11_GPIO, /* USB Vbus Enable */
+ MPP18_GPO, /* FAN High Enable# */
+ MPP19_GPO, /* FAN Low Enable# */
+ MPP36_GPIO, /* Function Blue LED */
+ MPP37_GPIO, /* Alarm LED */
+ MPP38_GPIO, /* Info LED */
+ MPP39_GPIO, /* Power LED */
+ MPP40_GPIO, /* Fan Lock */
+ MPP41_GPIO, /* Function Button */
+ MPP42_GPIO, /* Power Switch */
+ MPP43_GPIO, /* Power Auto Switch */
+ MPP48_GPIO, /* Function Red LED */
+ 0
+};
+
+/*****************************************************************************
+ * LS-XHL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-XHL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ *
+ */
+
+static void lsxhl_power_off(void)
+{
+ arm_machine_restart('h', NULL);
+}
+
+static void __init lsxhl_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(lsxhl_mpp_config);
+
+ /*
+ * Configure peripherals.
+ */
+ kirkwood_uart0_init();
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&lsxhl_ge00_data);
+ kirkwood_ge01_init(&lsxhl_ge01_data);
+ kirkwood_sata_init(&lsxhl_sata_data);
+ kirkwood_spi_init();
+
+ platform_device_register(&lsxhl_leds);
+ platform_device_register(&lsxhl_button_device);
+ platform_device_register(&lsxhl_fan_device);
+
+ spi_register_board_info(lsxhl_spi_slave_info,
+ ARRAY_SIZE(lsxhl_spi_slave_info));
+
+ /* usb power on */
+ gpio_set_value(LSXHL_GPIO_USB_POWER, 1);
+
+ /* register power-off method */
+ pm_power_off = lsxhl_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LSXHL, "Buffalo Linkstation LS-XHL")
+ .atag_offset = 0x100,
+ .init_machine = lsxhl_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 3b3776d..8acc587 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -448,6 +448,7 @@ mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650
guruplug MACH_GURUPLUG GURUPLUG 2659
spear310 MACH_SPEAR310 SPEAR310 2660
spear320 MACH_SPEAR320 SPEAR320 2661
+lsxhl MACH_LSXHL LSXHL 2663
aquila MACH_AQUILA AQUILA 2676
sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
--
1.7.2.3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
kirkwood and dove have a smaller FIFO than other "orion" SoCs. This
needs to be taken into account otherwise people using things like jumbo frames
will get into some troubles.
As a side note, this patch is an updated version of a patch sent some years
ago: http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/017320.html
which seems to have been lost.
Signed-off-by: Arnaud Patard <arnaud.patard@xxxxxxxxxxx>
Index: alunn/arch/arm/mach-dove/common.c
===================================================================
--- alunn.orig/arch/arm/mach-dove/common.c 2012-07-20 09:14:45.000000000 +0200
+++ alunn/arch/arm/mach-dove/common.c 2012-07-20 17:51:38.872925518 +0200
@@ -102,7 +102,7 @@ void __init dove_ehci1_init(void)
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data, DOVE_GE00_PHYS_BASE,
- IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR);
+ IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR, 0);
}
/*****************************************************************************
Index: alunn/arch/arm/mach-kirkwood/common.c
===================================================================
--- alunn.orig/arch/arm/mach-kirkwood/common.c 2012-07-20 09:14:46.000000000 +0200
+++ alunn/arch/arm/mach-kirkwood/common.c 2012-07-20 17:51:03.104927094 +0200
@@ -301,7 +301,7 @@ void __init kirkwood_ge00_init(struct mv
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
- IRQ_KIRKWOOD_GE00_ERR);
+ IRQ_KIRKWOOD_GE00_ERR, 1600);
/* The interface forgets the MAC address assigned by u-boot if
the clock is turned off, so claim the clk now. */
clk_prepare_enable(ge0);
@@ -315,7 +315,7 @@ void __init kirkwood_ge01_init(struct mv
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
- IRQ_KIRKWOOD_GE01_ERR);
+ IRQ_KIRKWOOD_GE01_ERR, 1600);
clk_prepare_enable(ge1);
}
Index: alunn/arch/arm/mach-mv78xx0/common.c
===================================================================
--- alunn.orig/arch/arm/mach-mv78xx0/common.c 2012-07-20 09:14:46.000000000 +0200
+++ alunn/arch/arm/mach-mv78xx0/common.c 2012-07-20 17:50:26.712928695 +0200
@@ -213,7 +213,7 @@ void __init mv78xx0_ge00_init(struct mv6
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
- IRQ_MV78XX0_GE_ERR);
+ IRQ_MV78XX0_GE_ERR, 0);
}
@@ -224,7 +224,7 @@ void __init mv78xx0_ge01_init(struct mv6
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
- NO_IRQ);
+ NO_IRQ, 0);
}
Index: alunn/arch/arm/mach-orion5x/common.c
===================================================================
--- alunn.orig/arch/arm/mach-orion5x/common.c 2012-07-20 09:14:46.000000000 +0200
+++ alunn/arch/arm/mach-orion5x/common.c 2012-07-20 17:50:26.744928692 +0200
@@ -109,7 +109,7 @@ void __init orion5x_eth_init(struct mv64
{
orion_ge00_init(eth_data,
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
- IRQ_ORION5X_ETH_ERR);
+ IRQ_ORION5X_ETH_ERR, 0);
}
Index: alunn/arch/arm/plat-orion/common.c
===================================================================
--- alunn.orig/arch/arm/plat-orion/common.c 2012-07-20 09:14:46.000000000 +0200
+++ alunn/arch/arm/plat-orion/common.c 2012-07-20 17:50:26.756928690 +0200
@@ -291,10 +291,12 @@ static struct platform_device orion_ge00
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err)
+ unsigned long irq_err,
+ unsigned int tx_csum_limit)
{
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge00_shared_data,
orion_ge00_resources, irq, &orion_ge00_shared,
eth_data, &orion_ge00);
@@ -343,10 +345,12 @@ static struct platform_device orion_ge01
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err)
+ unsigned long irq_err,
+ unsigned int tx_csum_limit)
{
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
+ orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
ge_complete(&orion_ge01_shared_data,
orion_ge01_resources, irq, &orion_ge01_shared,
eth_data, &orion_ge01);
Index: alunn/arch/arm/plat-orion/include/plat/common.h
===================================================================
--- alunn.orig/arch/arm/plat-orion/include/plat/common.h 2012-07-20 09:14:46.000000000 +0200
+++ alunn/arch/arm/plat-orion/include/plat/common.h 2012-07-20 17:50:26.772928691 +0200
@@ -39,12 +39,14 @@ void __init orion_rtc_init(unsigned long
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err);
+ unsigned long irq_err,
+ unsigned int tx_csum_limit);
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
- unsigned long irq_err);
+ unsigned long irq_err,
+ unsigned int tx_csum_limit);
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,

View File

@ -0,0 +1,15 @@
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=181963
--- linux-2.6.15.noarch/fs/fat/inode.c~ 2006-02-20 23:20:12.000000000 -0500
+++ linux-2.6.15.noarch/fs/fat/inode.c 2006-02-20 23:21:42.000000000 -0500
@@ -952,7 +952,8 @@ static int parse_options(char *options,
opts->shortname = 0;
opts->name_check = 'n';
opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0;
- opts->utf8 = opts->unicode_xlate = 0;
+ opts->utf8 = 1;
+ opts->unicode_xlate = 0;
opts->numtail = 1;
opts->nocase = 0;
*debug = 0;

View File

@ -0,0 +1,13 @@
* Optimise for today's CPUs.
--- linux-2.6/arch/x86/Makefile_32.cpu 2006-01-09 11:39:04.000000000 -0500
+++ linux-2.6/arch/x86/Makefile_32.cpu 2006-01-09 11:39:36.000000000 -0500
@@ -15,7 +15,7 @@ cflags-$(CONFIG_M486) += -march=i486
cflags-$(CONFIG_M586) += -march=i586
cflags-$(CONFIG_M586TSC) += -march=i586
cflags-$(CONFIG_M586MMX) += -march=pentium-mmx
-cflags-$(CONFIG_M686) += -march=i686
+cflags-$(CONFIG_M686) += -march=i686 $(call tune,generic)
cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call tune,pentium2)
cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call tune,pentium3)
cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call tune,pentium3)

File diff suppressed because it is too large Load Diff

201830
3.2.34/linux-3.2.33-zfs.patch Normal file

File diff suppressed because it is too large Load Diff

256
3.2.34/lschlv2.patch Normal file
View File

@ -0,0 +1,256 @@
--- a/arch/arm/mach-kirkwood/include/mach/system.h
+++ b/arch/arm/mach-kirkwood/include/mach/system.h
@@ -9,6 +9,8 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
+#include <linux/io.h>
+#include <asm/proc-fns.h>
#include <mach/bridge-regs.h>
static inline void arch_idle(void)
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -87,6 +87,12 @@
Say 'Y' here if you want your kernel to support the
HP t5325 Thin Client.
+config MACH_LINKSTATION_CHLV2
+ bool "Buffalo LS-CHLv2 Series"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo LS-CHLv2 Series.
+
endmenu
endif
--- a/arch/arm/mach-kirkwood/lschlv2-setup.c
+++ b/arch/arm/mach-kirkwood/lschlv2-setup.c
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-kirkwood/lschlv2-setup.c
+ *
+ * Buffalo LS Kirkwood Series Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include "include/mach/system.h"
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on BOOT Device
+ ****************************************************************************/
+static struct mtd_partition lschlv2_partitions[] = {
+ {
+ .name = "u-boot",
+ .offset = 0x00000,
+ .size = 0x70000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 0x10000,
+ }
+};
+
+static struct flash_platform_data lschlv2_spi_slave_data = {
+ .type = "m25p40",
+ .parts = lschlv2_partitions,
+ .nr_parts = ARRAY_SIZE(lschlv2_partitions),
+};
+
+static struct spi_board_info __initdata lschlv2_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lschlv2_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ }
+};
+
+static struct mv643xx_eth_platform_data lschlv2_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv643xx_eth_platform_data lschlv2_ge01_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+static unsigned int lschlv2_mpp_config[] __initdata = {
+ MPP10_GPO, /* HDD Power */
+ MPP11_GPIO, /* USB Vbus Power */
+ MPP18_GPO, /* FAN High on:0, off:1 */
+ MPP19_GPO, /* FAN Low on:0, off:1 */
+ MPP36_GPIO, /* FUNC LED */
+ MPP37_GPIO, /* ALARM LED */
+ MPP38_GPIO, /* INFO LED */
+ MPP39_GPIO, /* POWER LED */
+ MPP40_GPIO, /* FAN LOCK */
+ MPP41_GPIO, /* FUNC SW */
+ MPP42_GPIO, /* POWER SW */
+ MPP43_GPIO, /* POWER AUTO SW */
+ MPP48_GPIO, /* FUNC RED LED */
+ MPP49_GPIO, /* UART EN */
+ 0
+};
+
+static struct mv_sata_platform_data lschlv2_sata_data = {
+ .n_ports = 1,
+};
+
+static struct gpio_led lschlv2_led_pins[] = {
+ {
+ .name = "func",
+ .gpio = 36,
+ .active_low = 1,
+ },
+ {
+ .name = "alarm",
+ .gpio = 37,
+ .active_low = 1,
+ },
+ {
+ .name = "info",
+ .gpio = 38,
+ .active_low = 1,
+ },
+ {
+ .name = "power",
+ .gpio = 39,
+ .default_trigger = "default-on",
+ .active_low = 1,
+ },
+ {
+ .name = "func2",
+ .gpio = 48,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data lschlv2_led_data = {
+ .leds = lschlv2_led_pins,
+ .num_leds = ARRAY_SIZE(lschlv2_led_pins),
+};
+
+static struct platform_device lschlv2_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lschlv2_led_data,
+ }
+};
+
+#define LSCHLv2_GPIO_USB_VBUS_EN 11
+#define LSCHLv2_GPIO_KEY_FUNC 41
+
+static struct gpio_keys_button lschlv2_buttons[] = {
+ {
+ .code = KEY_OPTION,
+ .gpio = LSCHLv2_GPIO_KEY_FUNC,
+ .desc = "Function Button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data lschlv2_button_data = {
+ .buttons = lschlv2_buttons,
+ .nbuttons = ARRAY_SIZE(lschlv2_buttons),
+};
+
+static struct platform_device lschlv2_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lschlv2_button_data,
+ },
+};
+
+static void lschlv2_power_off(void)
+{
+ arch_reset(0, NULL);
+}
+
+static void __init lschlv2_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(lschlv2_mpp_config);
+
+ kirkwood_uart0_init();
+
+ if (gpio_request(LSCHLv2_GPIO_USB_VBUS_EN, "USB Power Enable") != 0 ||
+ gpio_direction_output(LSCHLv2_GPIO_USB_VBUS_EN, 1) != 0)
+ printk(KERN_ERR "can't set up USB Power Enable\n");
+ kirkwood_ehci_init();
+
+ kirkwood_ge00_init(&lschlv2_ge00_data);
+ kirkwood_ge01_init(&lschlv2_ge01_data);
+
+ kirkwood_sata_init(&lschlv2_sata_data);
+
+ kirkwood_spi_init();
+
+ platform_device_register(&lschlv2_leds);
+ platform_device_register(&lschlv2_button_device);
+
+ spi_register_board_info(lschlv2_spi_slave_info,
+ ARRAY_SIZE(lschlv2_spi_slave_info));
+
+ /* register power-off method */
+ pm_power_off = lschlv2_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+
+
+MACHINE_START(LINKSTATION_CHLV2, "Buffalo Linkstation LS-CHLv2")
+ .atag_offset = 0x100,
+ .init_machine = lschlv2_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -20,3 +20,4 @@
obj-$(CONFIG_MACH_T5325) += t5325-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_CHLV2) += lschlv2-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -32,6 +32,7 @@
#include <plat/orion_nand.h>
#include <plat/orion_wdt.h>
#include <plat/time.h>
+#include <asm/mach-types.h>
#include "common.h"
/*****************************************************************************

View File

@ -0,0 +1,32 @@
--- linux-2.6.35-rc6-git-mnb0.1/net/ipv4/netfilter/ipt_IFWLOG.c.orig 2010-07-30 21:17:30.000000000 +0300
+++ linux-2.6.35-rc6-git-mnb0.1/net/ipv4/netfilter/ipt_IFWLOG.c 2010-07-31 13:46:33.834611944 +0300
@@ -135,7 +135,7 @@ static void ipt_IFWLOG_packet(const stru
}
static unsigned int ipt_IFWLOG_target(struct sk_buff *skb,
- const struct xt_target_param *target_param)
+ const struct xt_action_param *target_param)
{
const struct ipt_IFWLOG_info *info = target_param->targinfo;
@@ -144,17 +144,17 @@ static unsigned int ipt_IFWLOG_target(st
return IPT_CONTINUE;
}
-static bool ipt_IFWLOG_checkentry(const struct xt_tgchk_param *tgchk_param)
+static int ipt_IFWLOG_checkentry(const struct xt_tgchk_param *tgchk_param)
{
const struct ipt_IFWLOG_info *info = tgchk_param->targinfo;
if (info->prefix[sizeof(info->prefix)-1] != '\0') {
DEBUGP("IFWLOG: prefix term %i\n",
info->prefix[sizeof(info->prefix)-1]);
- return false;
+ return -EINVAL;
}
- return true;
+ return 0;
}
static struct xt_target ipt_IFWLOG = {

View File

@ -0,0 +1,15 @@
net/ipv4/netfilter/ipt_IFWLOG.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- linux-2.6.37-rc3-git1-tmb0.3/net/ipv4/netfilter/ipt_IFWLOG.c.orig 2010-11-24 21:58:36.000000000 +0200
+++ linux-2.6.37-rc3-git1-tmb0.3/net/ipv4/netfilter/ipt_IFWLOG.c 2010-11-25 13:08:55.719379646 +0200
@@ -141,7 +141,7 @@ static unsigned int ipt_IFWLOG_target(st
ipt_IFWLOG_packet(skb, target_param->in, target_param->out, info);
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static int ipt_IFWLOG_checkentry(const struct xt_tgchk_param *tgchk_param)

View File

@ -0,0 +1,264 @@
ipt_IFWLOG: Mandriva changes
This patch holds all the Mandriva changes done in ipt_IFWLOG
netfilter module.
This work is mostly done by Thomas Backlund, Herton R. Krzesinski
and Luiz Fernando N. Capitulino.
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
include/linux/netfilter_ipv4/Kbuild | 1
include/linux/netfilter_ipv4/ipt_IFWLOG.h | 23 +++++-
net/ipv4/netfilter/ipt_IFWLOG.c | 108 +++++++++++++++---------------
3 files changed, 77 insertions(+), 55 deletions(-)
diff -p -up linux-2.6.28/include/linux/netfilter_ipv4/ipt_IFWLOG.h.orig linux-2.6.28/include/linux/netfilter_ipv4/ipt_IFWLOG.h
--- linux-2.6.28/include/linux/netfilter_ipv4/ipt_IFWLOG.h.orig 2008-12-12 10:55:07.000000000 -0500
+++ linux-2.6.28/include/linux/netfilter_ipv4/ipt_IFWLOG.h 2008-12-12 10:56:30.000000000 -0500
@@ -1,10 +1,25 @@
-#ifndef _IPT_IFWLOG_H
-#define _IPT_IFWLOG_H
+#ifndef _LINUX_IPT_IFWLOG_H
+#define _LINUX_IPT_IFWLOG_H
#ifndef NETLINK_IFWLOG
-#define NETLINK_IFWLOG 19
+#define NETLINK_IFWLOG 20
#endif
+#ifndef __KERNEL__
+/* Multicast groups - backwards compatiblility for userspace */
+#define IFWLOG_NLGRP_NONE 0x00000000
+#define IFWLOG_NLGRP_DEF 0x00000001 /* default message group */
+#endif
+
+enum {
+ IFWLOGNLGRP_NONE,
+#define IFWLOGNLGRP_NONE IFWLOGNLGRP_NONE
+ IFWLOGNLGRP_DEF,
+#define IFWLOGNLGRP_DEF IFWLOGNLGRP_DEF
+ __IFWLOGNLGRP_MAX
+};
+#define IFWLOGNLGRP_MAX (__IFWLOGNLGRP_MAX - 1)
+
#define PREFSIZ 32
struct nl_msg { /* Netlink message */
@@ -23,4 +38,4 @@ struct ipt_IFWLOG_info {
char prefix[PREFSIZ];
};
-#endif /* _IPT_IFWLOG_H */
+#endif /* _LINUX_IPT_IFWLOG_H */
diff -p -up linux-2.6.28/net/ipv4/netfilter/ipt_IFWLOG.c.orig linux-2.6.28/net/ipv4/netfilter/ipt_IFWLOG.c
--- linux-2.6.28/net/ipv4/netfilter/ipt_IFWLOG.c.orig 2008-12-12 10:55:07.000000000 -0500
+++ linux-2.6.28/net/ipv4/netfilter/ipt_IFWLOG.c 2008-12-12 10:57:16.000000000 -0500
@@ -4,6 +4,14 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
+ *
+ * 2007-10-10 Thomas Backlund <tmb@mandriva.org>: build fixes for 2.6.22.9
+ * 2007-11-11 Herton Krzesinski <herton@mandriva.com>: build fixes for 2.6.24-rc
+ * 2007-12-03 Luiz Capitulino <lcapitulino@mandriva.com.br>: v1.1
+ * - Better multicast group usage
+ * - Coding style fixes
+ * - Do not return -EINVAL by default in ipt_ifwlog_init()
+ * - Minor refinements
*/
#include <linux/module.h>
@@ -19,12 +27,10 @@
#include <linux/string.h>
#include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_IFWLOG.h>
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Samir Bellabes <sbellabes@mandriva.com>");
-MODULE_DESCRIPTION("Interactive firewall logging and module");
#if 0
#define DEBUGP PRINTR
@@ -36,44 +42,41 @@ MODULE_DESCRIPTION("Interactive firewall
static struct sock *nl;
-#define GROUP 10
-
/* send struct to userspace */
-static void send_packet(struct nl_msg msg)
+static void send_packet(const struct nl_msg *msg)
{
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
+ unsigned int size;
- skb = alloc_skb(NLMSG_SPACE(sizeof(struct nl_msg)), GFP_ATOMIC);
+ size = NLMSG_SPACE(sizeof(*msg));
+ skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
PRINTR(KERN_WARNING "IFWLOG: OOM can't allocate skb\n");
- return ;
+ return;
}
- nlh = NLMSG_PUT(skb, 0, 0, 0, sizeof(struct nl_msg) - sizeof(*nlh));
+ nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh));
- memcpy(NLMSG_DATA(nlh), (const void*)&msg, sizeof(struct nl_msg));
+ memcpy(NLMSG_DATA(nlh), (const void *) msg, sizeof(*msg));
NETLINK_CB(skb).pid = 0; /* from kernel */
- NETLINK_CB(skb).dst_pid = 0; /* multicast */
- NETLINK_CB(skb).dst_group = 10;
+ NETLINK_CB(skb).dst_group = IFWLOGNLGRP_DEF;
if (nl) {
DEBUGP(KERN_WARNING
"IFWLOG: nlmsg_len=%ld\nnlmsg_type=%d nlmsg_flags=%d\nnlmsg_seq=%ld nlmsg_pid = %ld\n",
(long)nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
(long)nlh->nlmsg_seq, (long)nlh->nlmsg_pid);
- DEBUGP(KERN_WARNING "prefix : %s\n", msg.prefix);
+ DEBUGP(KERN_WARNING "prefix : %s\n", msg->prefix);
- netlink_broadcast(nl, skb, 0, 10, GFP_ATOMIC);
- return ;
+ netlink_broadcast(nl, skb, 0, IFWLOGNLGRP_DEF, GFP_ATOMIC);
+ return;
}
- nlmsg_failure:
- if (skb)
- kfree_skb(skb);
- PRINTR(KERN_WARNING "IFWLOG: Error sending netlink packet\n");
- return ;
+nlmsg_failure:
+ kfree_skb(skb);
+ PRINTR(KERN_WARNING "IFWLOG: Error sending netlink packet\n");
}
/* fill struct for userspace */
@@ -128,73 +131,76 @@ static void ipt_IFWLOG_packet(const stru
do_gettimeofday((struct timeval *)&tv);
msg.timestamp_sec = tv.tv_sec;
- send_packet(msg);
+ send_packet(&msg);
}
-static unsigned int ipt_IFWLOG_target(struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const void *targinfo,
- void *userinfo)
+static unsigned int ipt_IFWLOG_target(struct sk_buff *skb,
+ const struct xt_target_param *target_param)
{
- const struct ipt_IFWLOG_info *info = targinfo;
+ const struct ipt_IFWLOG_info *info = target_param->targinfo;
- ipt_IFWLOG_packet(*pskb, in, out, info);
+ ipt_IFWLOG_packet(skb, target_param->in, target_param->out, info);
return IPT_CONTINUE;
}
-static int ipt_IFWLOG_checkentry(const char *tablename,
- const struct ipt_entry *e,
- void *targinfo,
- unsigned int targinfosize,
- unsigned int hook_mask)
+static bool ipt_IFWLOG_checkentry(const struct xt_tgchk_param *tgchk_param)
{
- const struct ipt_IFWLOG_info *info = targinfo;
+ const struct ipt_IFWLOG_info *info = tgchk_param->targinfo;
if (info->prefix[sizeof(info->prefix)-1] != '\0') {
DEBUGP("IFWLOG: prefix term %i\n",
info->prefix[sizeof(info->prefix)-1]);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct ipt_target ipt_IFWLOG = {
+static struct xt_target ipt_IFWLOG = {
.name = "IFWLOG",
+ .family = AF_INET,
.target = ipt_IFWLOG_target,
.targetsize = sizeof(struct ipt_IFWLOG_info),
.checkentry = ipt_IFWLOG_checkentry,
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ifwlog_init(void)
{
- nl = (struct sock*) netlink_kernel_create(NETLINK_IFWLOG, GROUP, NULL, THIS_MODULE);
- if (!nl) {
- PRINTR(KERN_WARNING "IFWLOG: cannot create netlink socket\n");
- return -EINVAL;
- }
+ int err;
- if (ipt_register_target(&ipt_IFWLOG)) {
+ nl = netlink_kernel_create(&init_net, NETLINK_IFWLOG, IFWLOGNLGRP_MAX,
+ NULL, NULL, THIS_MODULE);
+ if (!nl) {
+ PRINTR(KERN_WARNING "IFWLOG: cannot create netlink socket\n");
+ return -ENOMEM;
+ }
+
+ err = xt_register_target(&ipt_IFWLOG);
+ if (err) {
if (nl && nl->sk_socket)
sock_release(nl->sk_socket);
- return -EINVAL;
+ return err;
}
PRINTR(KERN_INFO "IFWLOG: register target\n");
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_ifwlog_fini(void)
{
if (nl && nl->sk_socket)
- sock_release(nl->sk_socket);
+ sock_release(nl->sk_socket);
PRINTR(KERN_INFO "IFWLOG: unregister target\n");
- ipt_unregister_target(&ipt_IFWLOG);
+ xt_unregister_target(&ipt_IFWLOG);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ifwlog_init);
+module_exit(ipt_ifwlog_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Samir Bellabes <sbellabes@mandriva.com>");
+MODULE_AUTHOR("Luiz Capitulino <lcapitulino@mandriva.com.br>");
+MODULE_DESCRIPTION("Interactive firewall logging and module");
+MODULE_VERSION("v1.1");
--- linux/include/linux/netfilter_ipv4/Kbuild.net-netfilter-IFWLOG-mdv.orig 2012-05-21 01:29:13.000000000 +0300
+++ linux/include/linux/netfilter_ipv4/Kbuild 2012-05-26 01:27:24.743139430 +0300
@@ -2,6 +2,7 @@ header-y += ip_queue.h
header-y += ip_tables.h
header-y += ipt_CLUSTERIP.h
header-y += ipt_ECN.h
+header-y += ipt_IFWLOG.h
header-y += ipt_LOG.h
header-y += ipt_REJECT.h
header-y += ipt_TTL.h

View File

@ -0,0 +1,269 @@
---
include/linux/netfilter_ipv4/ipt_IFWLOG.h | 26 +++
net/ipv4/netfilter/Kconfig | 11 +
net/ipv4/netfilter/Makefile | 1
net/ipv4/netfilter/ipt_IFWLOG.c | 200 ++++++++++++++++++++++++++++++
4 files changed, 238 insertions(+)
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_IFWLOG.c
@@ -0,0 +1,200 @@
+/* Interactive Firewall for Mandriva
+ * Samir Bellabes <sbellabes@mandriva.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <asm/types.h>
+#include <linux/jiffies.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <linux/netlink.h>
+#include <linux/string.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_IFWLOG.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Samir Bellabes <sbellabes@mandriva.com>");
+MODULE_DESCRIPTION("Interactive firewall logging and module");
+
+#if 0
+#define DEBUGP PRINTR
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define PRINTR(format, args...) do { if(net_ratelimit()) printk(format, ##args); } while(0)
+
+static struct sock *nl;
+
+#define GROUP 10
+
+/* send struct to userspace */
+static void send_packet(struct nl_msg msg)
+{
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nlh;
+
+ skb = alloc_skb(NLMSG_SPACE(sizeof(struct nl_msg)), GFP_ATOMIC);
+ if (!skb) {
+ PRINTR(KERN_WARNING "IFWLOG: OOM can't allocate skb\n");
+ return ;
+ }
+
+ nlh = NLMSG_PUT(skb, 0, 0, 0, sizeof(struct nl_msg) - sizeof(*nlh));
+
+ memcpy(NLMSG_DATA(nlh), (const void*)&msg, sizeof(struct nl_msg));
+
+ NETLINK_CB(skb).pid = 0; /* from kernel */
+ NETLINK_CB(skb).dst_pid = 0; /* multicast */
+ NETLINK_CB(skb).dst_group = 10;
+
+ if (nl) {
+ DEBUGP(KERN_WARNING
+ "IFWLOG: nlmsg_len=%ld\nnlmsg_type=%d nlmsg_flags=%d\nnlmsg_seq=%ld nlmsg_pid = %ld\n",
+ (long)nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
+ (long)nlh->nlmsg_seq, (long)nlh->nlmsg_pid);
+ DEBUGP(KERN_WARNING "prefix : %s\n", msg.prefix);
+
+ netlink_broadcast(nl, skb, 0, 10, GFP_ATOMIC);
+ return ;
+ }
+
+ nlmsg_failure:
+ if (skb)
+ kfree_skb(skb);
+ PRINTR(KERN_WARNING "IFWLOG: Error sending netlink packet\n");
+ return ;
+}
+
+/* fill struct for userspace */
+static void ipt_IFWLOG_packet(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct ipt_IFWLOG_info *info)
+{
+ struct iphdr iph;
+ struct tcphdr tcph;
+ struct udphdr udph;
+ struct nl_msg msg;
+ struct iphdr _iph, *ih;
+ struct timeval tv;
+
+ memset(&msg, 0, sizeof(struct nl_msg));
+
+ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+ if (ih == NULL) {
+ PRINTR(KERN_WARNING "IFWLOG: skb truncated");
+ return;
+ }
+
+ /* save interface name */
+ if (in)
+ strcpy(msg.indev_name, in->name);
+ if (out)
+ strcpy(msg.outdev_name, out->name);
+
+ /* save log-prefix */
+ strcpy(msg.prefix, info->prefix);
+
+ /* save ip header */
+ skb_copy_bits(skb, 0, &iph, sizeof(iph));
+ memcpy(&msg.ip, &iph, sizeof(struct iphdr));
+
+ /* save transport header */
+ switch (iph.protocol){
+ case IPPROTO_TCP:
+ skb_copy_bits(skb, iph.ihl*4 , &tcph, sizeof(tcph));
+ memcpy(&msg.h.th, &tcph, sizeof(struct tcphdr));
+ break;
+ case IPPROTO_UDP:
+ skb_copy_bits(skb, iph.ihl*4 , &udph, sizeof(udph));
+ memcpy(&msg.h.uh, &udph, sizeof(struct udphdr));
+ break;
+ default:
+ break;
+ }
+
+ /* save timetamp */
+ do_gettimeofday((struct timeval *)&tv);
+ msg.timestamp_sec = tv.tv_sec;
+
+ send_packet(msg);
+}
+
+static unsigned int ipt_IFWLOG_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_IFWLOG_info *info = targinfo;
+
+ ipt_IFWLOG_packet(*pskb, in, out, info);
+
+ return IPT_CONTINUE;
+}
+
+static int ipt_IFWLOG_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ const struct ipt_IFWLOG_info *info = targinfo;
+
+ if (info->prefix[sizeof(info->prefix)-1] != '\0') {
+ DEBUGP("IFWLOG: prefix term %i\n",
+ info->prefix[sizeof(info->prefix)-1]);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_IFWLOG = {
+ .name = "IFWLOG",
+ .target = ipt_IFWLOG_target,
+ .targetsize = sizeof(struct ipt_IFWLOG_info),
+ .checkentry = ipt_IFWLOG_checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ nl = (struct sock*) netlink_kernel_create(NETLINK_IFWLOG, GROUP, NULL, THIS_MODULE);
+ if (!nl) {
+ PRINTR(KERN_WARNING "IFWLOG: cannot create netlink socket\n");
+ return -EINVAL;
+ }
+
+ if (ipt_register_target(&ipt_IFWLOG)) {
+ if (nl && nl->sk_socket)
+ sock_release(nl->sk_socket);
+ return -EINVAL;
+ }
+
+ PRINTR(KERN_INFO "IFWLOG: register target\n");
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ if (nl && nl->sk_socket)
+ sock_release(nl->sk_socket);
+ PRINTR(KERN_INFO "IFWLOG: unregister target\n");
+ ipt_unregister_target(&ipt_IFWLOG);
+}
+
+module_init(init);
+module_exit(fini);
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -331,6 +331,17 @@ config IP_NF_TARGET_TTL
(e.g. when running oldconfig). It selects
CONFIG_NETFILTER_XT_TARGET_HL.
+config IP_NF_TARGET_IFWLOG
+ tristate 'IFWLOG target support'
+ depends on IP_NF_IPTABLES
+ help
+ This option adds a `IFWLOG' target, which is used by
+ Interactive Firewall for sending informations to a userspace
+ daemon
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
# raw + specific targets
config IP_NF_RAW
tristate 'raw table support (required for NOTRACK/TRACE)'
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_IFWLOG.h
@@ -0,0 +1,26 @@
+#ifndef _IPT_IFWLOG_H
+#define _IPT_IFWLOG_H
+
+#ifndef NETLINK_IFWLOG
+#define NETLINK_IFWLOG 19
+#endif
+
+#define PREFSIZ 32
+
+struct nl_msg { /* Netlink message */
+ long timestamp_sec; /* time packet */
+ char indev_name[IFNAMSIZ]; /* name of the ingoing interface */
+ char outdev_name[IFNAMSIZ]; /* name of the outgoing interface */
+ unsigned char prefix[PREFSIZ]; /* informations on the logging reason */
+ struct iphdr ip;
+ union {
+ struct tcphdr th;
+ struct udphdr uh;
+ } h;
+};
+
+struct ipt_IFWLOG_info {
+ char prefix[PREFSIZ];
+};
+
+#endif /* _IPT_IFWLOG_H */
--- linux/net/ipv4/netfilter/Makefile.net-netfilter-IFWLOG.orig 2012-05-21 01:29:13.000000000 +0300
+++ linux/net/ipv4/netfilter/Makefile 2012-05-26 01:23:57.511514194 +0300
@@ -53,6 +53,7 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ip
# targets
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
+obj-$(CONFIG_IP_NF_TARGET_IFWLOG) += ipt_IFWLOG.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o

View File

@ -0,0 +1,11 @@
--- linux-2.6.35-rc6-git-mnb0.1/net/ipv4/netfilter/ipt_psd.c.orig 2010-07-30 21:17:30.000000000 +0300
+++ linux-2.6.35-rc6-git-mnb0.1/net/ipv4/netfilter/ipt_psd.c 2010-07-31 13:29:00.623601957 +0300
@@ -98,7 +98,7 @@ static inline int hashfunc(struct in_add
static bool
ipt_psd_match(const struct sk_buff *pskb,
- const struct xt_match_param *match_param)
+ struct xt_action_param *match_param)
{
struct iphdr *ip_hdr;
struct tcphdr *tcp_hdr;

View File

@ -0,0 +1,235 @@
ipt_psd: Mandriva changes
This patch holds all the Mandriva changes done in ipt_psd
netfilter module.
Most of the time they're just upgrades to match with new
API in the kernel.
This work is mostly done by Thomas Backlund, Herton R.
Krzesinski and Luiz Fernando N. Capitulino.
Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
include/linux/netfilter_ipv4/Kbuild | 1
net/ipv4/netfilter/Kconfig | 8 ++
net/ipv4/netfilter/ipt_psd.c | 113 ++++++++++++++----------------------
3 files changed, 55 insertions(+), 67 deletions(-)
diff -p -up linux-2.6.28/net/ipv4/netfilter/ipt_psd.c.orig linux-2.6.28/net/ipv4/netfilter/ipt_psd.c
--- linux-2.6.28/net/ipv4/netfilter/ipt_psd.c.orig 2008-12-12 11:03:05.000000000 -0500
+++ linux-2.6.28/net/ipv4/netfilter/ipt_psd.c 2008-12-12 11:04:03.000000000 -0500
@@ -1,21 +1,24 @@
/*
- This is a module which is used for PSD (portscan detection)
- Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
- and LOG target module.
-
- Copyright (C) 2000,2001 astaro AG
-
- This file is distributed under the terms of the GNU General Public
- License (GPL). Copies of the GPL can be obtained from:
- ftp://prep.ai.mit.edu/pub/gnu/GPL
-
- 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
- 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
- 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
- 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
- 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
- 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
-*/
+ * This is a module which is used for PSD (portscan detection)
+ * Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
+ * and LOG target module.
+ *
+ * Copyright (C) 2000,2001 astaro AG
+ *
+ * This file is distributed under the terms of the GNU General Public
+ * License (GPL). Copies of the GPL can be obtained from:
+ * ftp://prep.ai.mit.edu/pub/gnu/GPL
+ *
+ * 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
+ * 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
+ * 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
+ * 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
+ * 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
+ * 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
+ * 2007-10-10 Thomas Backlund <tmb@mandriva.org>: 2.6.22 update
+ * 2007-11-14 Luiz Capitulino <lcapitulino@mandriva.com> : 2.6.22 API usage fixes
+ * 2007-11-26 Herton Ronaldo Krzesinski <herton@mandriva.com>: switch xt_match->match to bool
+ */
#include <linux/module.h>
#include <linux/skbuff.h>
@@ -54,7 +57,7 @@ struct port {
*/
struct host {
struct host *next; /* Next entry with the same hash */
- clock_t timestamp; /* Last update time */
+ unsigned long timestamp; /* Last update time */
struct in_addr src_addr; /* Source address */
struct in_addr dest_addr; /* Destination address */
unsigned short src_port; /* Source port */
@@ -93,33 +96,29 @@ static inline int hashfunc(struct in_add
return hash & (HASH_SIZE - 1);
}
-static int
+static bool
ipt_psd_match(const struct sk_buff *pskb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- int *hotdrop)
+ const struct xt_match_param *match_param)
{
struct iphdr *ip_hdr;
struct tcphdr *tcp_hdr;
struct in_addr addr;
u_int16_t src_port,dest_port;
u_int8_t tcp_flags, proto;
- clock_t now;
+ unsigned long now;
struct host *curr, *last, **head;
int hash, index, count;
/* Parameters from userspace */
- const struct ipt_psd_info *psdinfo = matchinfo;
+ const struct ipt_psd_info *psdinfo = match_param->matchinfo;
/* IP header */
- ip_hdr = pskb->nh.iph;
+ ip_hdr = ipip_hdr(pskb);
/* Sanity check */
if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
DEBUGP("PSD: sanity check failed\n");
- return 0;
+ return false;
}
/* TCP or UDP ? */
@@ -127,7 +126,7 @@ ipt_psd_match(const struct sk_buff *pskb
if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
DEBUGP("PSD: protocol not supported\n");
- return 0;
+ return false;
}
/* Get the source address, source & destination ports, and TCP flags */
@@ -151,7 +150,7 @@ ipt_psd_match(const struct sk_buff *pskb
* them spoof us. [DHCP needs this feature - HW] */
if (!addr.s_addr) {
DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
- return 0;
+ return false;
}
/* Use jiffies here not to depend on someone setting the time while we're
@@ -298,46 +297,26 @@ ipt_psd_match(const struct sk_buff *pskb
out_no_match:
spin_unlock(&state.lock);
- return 0;
+ return false;
out_match:
spin_unlock(&state.lock);
- return 1;
+ DEBUGP("PSD: Dropping packets from "NIPQUAD_FMT" \n",
+ NIPQUAD(curr->src_addr.s_addr));
+ return true;
}
-static int ipt_psd_checkentry(const char *tablename,
- const struct ipt_ip *e,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
-/* const struct ipt_psd_info *psdinfo = targinfo;*/
-
- /* we accept TCP only */
-/* if (e->ip.proto != IPPROTO_TCP) { */
-/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
-/* return 0; */
-/* } */
-
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
- DEBUGP("PSD: matchsize %u != %u\n",
- matchsize,
- IPT_ALIGN(sizeof(struct ipt_psd_info)));
- return 0;
- }
-
- return 1;
-}
-
-static struct ipt_match ipt_psd_reg = {
- .name = "psd",
- .match = ipt_psd_match,
- .checkentry = ipt_psd_checkentry,
- .me = THIS_MODULE };
+static struct xt_match ipt_psd_reg = {
+ .name = "psd",
+ .family = AF_INET,
+ .match = ipt_psd_match,
+ .matchsize = sizeof(struct ipt_psd_info),
+ .me = THIS_MODULE
+};
-static int __init init(void)
+static int __init ipt_psd_init(void)
{
- if (ipt_register_match(&ipt_psd_reg))
+ if (xt_register_match(&ipt_psd_reg))
return -EINVAL;
memset(&state, 0, sizeof(state));
@@ -348,11 +327,11 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_psd_fini(void)
{
- ipt_unregister_match(&ipt_psd_reg);
+ xt_unregister_match(&ipt_psd_reg);
printk("netfilter PSD unloaded - (c) astaro AG\n");
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_psd_init);
+module_exit(ipt_psd_fini);
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -322,6 +322,14 @@
(e.g. when running oldconfig). It selects
CONFIG_NETFILTER_XT_TARGET_HL.
+config IP_NF_MATCH_PSD
+ tristate 'Port scanner detection support'
+ depends on NETFILTER_ADVANCED
+ help
+ Module used for PSD (portscan detection).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_TARGET_IFWLOG
tristate 'IFWLOG target support'
depends on IP_NF_IPTABLES
--- linux/include/linux/netfilter_ipv4/Kbuild.net-netfilter-psd-mdv.orig 2012-05-26 01:28:56.000000000 +0300
+++ linux/include/linux/netfilter_ipv4/Kbuild 2012-05-26 01:30:21.493540796 +0300
@@ -11,6 +11,7 @@
header-y += ipt_addrtype.h
header-y += ipt_ah.h
header-y += ipt_ecn.h
+header-y += ipt_psd.h
header-y += ipt_realm.h
header-y += ipt_ttl.h
header-y += nf_nat.h

View File

@ -0,0 +1,420 @@
---
include/linux/netfilter_ipv4/ipt_psd.h | 40 +++
net/ipv4/netfilter/Makefile | 1
net/ipv4/netfilter/ipt_psd.c | 358 +++++++++++++++++++++++++++++++++
3 files changed, 399 insertions(+)
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_psd.c
@@ -0,0 +1,358 @@
+/*
+ This is a module which is used for PSD (portscan detection)
+ Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
+ and LOG target module.
+
+ Copyright (C) 2000,2001 astaro AG
+
+ This file is distributed under the terms of the GNU General Public
+ License (GPL). Copies of the GPL can be obtained from:
+ ftp://prep.ai.mit.edu/pub/gnu/GPL
+
+ 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
+ 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
+ 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
+ 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
+ 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
+ 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/tcp.h>
+#include <linux/spinlock.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_psd.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
+
+#define HF_DADDR_CHANGING 0x01
+#define HF_SPORT_CHANGING 0x02
+#define HF_TOS_CHANGING 0x04
+#define HF_TTL_CHANGING 0x08
+
+/*
+ * Information we keep per each target port
+ */
+struct port {
+ u_int16_t number; /* port number */
+ u_int8_t proto; /* protocol number */
+ u_int8_t and_flags; /* tcp ANDed flags */
+ u_int8_t or_flags; /* tcp ORed flags */
+};
+
+/*
+ * Information we keep per each source address.
+ */
+struct host {
+ struct host *next; /* Next entry with the same hash */
+ clock_t timestamp; /* Last update time */
+ struct in_addr src_addr; /* Source address */
+ struct in_addr dest_addr; /* Destination address */
+ unsigned short src_port; /* Source port */
+ int count; /* Number of ports in the list */
+ int weight; /* Total weight of ports in the list */
+ struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
+ unsigned char tos; /* TOS */
+ unsigned char ttl; /* TTL */
+ unsigned char flags; /* HF_ flags bitmask */
+};
+
+/*
+ * State information.
+ */
+static struct {
+ spinlock_t lock;
+ struct host list[LIST_SIZE]; /* List of source addresses */
+ struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
+ int index; /* Oldest entry to be replaced */
+} state;
+
+/*
+ * Convert an IP address into a hash table index.
+ */
+static inline int hashfunc(struct in_addr addr)
+{
+ unsigned int value;
+ int hash;
+
+ value = addr.s_addr;
+ hash = 0;
+ do {
+ hash ^= value;
+ } while ((value >>= HASH_LOG));
+
+ return hash & (HASH_SIZE - 1);
+}
+
+static int
+ipt_psd_match(const struct sk_buff *pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ int *hotdrop)
+{
+ struct iphdr *ip_hdr;
+ struct tcphdr *tcp_hdr;
+ struct in_addr addr;
+ u_int16_t src_port,dest_port;
+ u_int8_t tcp_flags, proto;
+ clock_t now;
+ struct host *curr, *last, **head;
+ int hash, index, count;
+
+ /* Parameters from userspace */
+ const struct ipt_psd_info *psdinfo = matchinfo;
+
+ /* IP header */
+ ip_hdr = pskb->nh.iph;
+
+ /* Sanity check */
+ if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
+ DEBUGP("PSD: sanity check failed\n");
+ return 0;
+ }
+
+ /* TCP or UDP ? */
+ proto = ip_hdr->protocol;
+
+ if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
+ DEBUGP("PSD: protocol not supported\n");
+ return 0;
+ }
+
+ /* Get the source address, source & destination ports, and TCP flags */
+
+ addr.s_addr = ip_hdr->saddr;
+
+ tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
+
+ /* Yep, it´s dirty */
+ src_port = tcp_hdr->source;
+ dest_port = tcp_hdr->dest;
+
+ if (proto == IPPROTO_TCP) {
+ tcp_flags = *((u_int8_t*)tcp_hdr + 13);
+ }
+ else {
+ tcp_flags = 0x00;
+ }
+
+ /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
+ * them spoof us. [DHCP needs this feature - HW] */
+ if (!addr.s_addr) {
+ DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
+ return 0;
+ }
+
+ /* Use jiffies here not to depend on someone setting the time while we're
+ * running; we need to be careful with possible return value overflows. */
+ now = jiffies;
+
+ spin_lock(&state.lock);
+
+ /* Do we know this source address already? */
+ count = 0;
+ last = NULL;
+ if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
+ do {
+ if (curr->src_addr.s_addr == addr.s_addr) break;
+ count++;
+ if (curr->next) last = curr;
+ } while ((curr = curr->next));
+
+ if (curr) {
+
+ /* We know this address, and the entry isn't too old. Update it. */
+ if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
+ time_after_eq(now, curr->timestamp)) {
+
+ /* Just update the appropriate list entry if we've seen this port already */
+ for (index = 0; index < curr->count; index++) {
+ if (curr->ports[index].number == dest_port) {
+ curr->ports[index].proto = proto;
+ curr->ports[index].and_flags &= tcp_flags;
+ curr->ports[index].or_flags |= tcp_flags;
+ goto out_no_match;
+ }
+ }
+
+ /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
+ if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
+ goto out_no_match;
+
+ /* Packet to a new port, and not TCP/ACK: update the timestamp */
+ curr->timestamp = now;
+
+ /* Logged this scan already? Then drop the packet. */
+ if (curr->weight >= psdinfo->weight_threshold)
+ goto out_match;
+
+ /* Specify if destination address, source port, TOS or TTL are not fixed */
+ if (curr->dest_addr.s_addr != ip_hdr->daddr)
+ curr->flags |= HF_DADDR_CHANGING;
+ if (curr->src_port != src_port)
+ curr->flags |= HF_SPORT_CHANGING;
+ if (curr->tos != ip_hdr->tos)
+ curr->flags |= HF_TOS_CHANGING;
+ if (curr->ttl != ip_hdr->ttl)
+ curr->flags |= HF_TTL_CHANGING;
+
+ /* Update the total weight */
+ curr->weight += (ntohs(dest_port) < 1024) ?
+ psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
+
+ /* Got enough destination ports to decide that this is a scan? */
+ /* Then log it and drop the packet. */
+ if (curr->weight >= psdinfo->weight_threshold)
+ goto out_match;
+
+ /* Remember the new port */
+ if (curr->count < SCAN_MAX_COUNT) {
+ curr->ports[curr->count].number = dest_port;
+ curr->ports[curr->count].proto = proto;
+ curr->ports[curr->count].and_flags = tcp_flags;
+ curr->ports[curr->count].or_flags = tcp_flags;
+ curr->count++;
+ }
+
+ goto out_no_match;
+ }
+
+ /* We know this address, but the entry is outdated. Mark it unused, and
+ * remove from the hash table. We'll allocate a new entry instead since
+ * this one might get re-used too soon. */
+ curr->src_addr.s_addr = 0;
+ if (last)
+ last->next = last->next->next;
+ else if (*head)
+ *head = (*head)->next;
+ last = NULL;
+ }
+
+ /* We don't need an ACK from a new source address */
+ if (proto == IPPROTO_TCP && tcp_hdr->ack)
+ goto out_no_match;
+
+ /* Got too many source addresses with the same hash value? Then remove the
+ * oldest one from the hash table, so that they can't take too much of our
+ * CPU time even with carefully chosen spoofed IP addresses. */
+ if (count >= HASH_MAX && last) last->next = NULL;
+
+ /* We're going to re-use the oldest list entry, so remove it from the hash
+ * table first (if it is really already in use, and isn't removed from the
+ * hash table already because of the HASH_MAX check above). */
+
+ /* First, find it */
+ if (state.list[state.index].src_addr.s_addr)
+ head = &state.hash[hashfunc(state.list[state.index].src_addr)];
+ else
+ head = &last;
+ last = NULL;
+ if ((curr = *head))
+ do {
+ if (curr == &state.list[state.index]) break;
+ last = curr;
+ } while ((curr = curr->next));
+
+ /* Then, remove it */
+ if (curr) {
+ if (last)
+ last->next = last->next->next;
+ else if (*head)
+ *head = (*head)->next;
+ }
+
+ /* Get our list entry */
+ curr = &state.list[state.index++];
+ if (state.index >= LIST_SIZE) state.index = 0;
+
+ /* Link it into the hash table */
+ head = &state.hash[hash];
+ curr->next = *head;
+ *head = curr;
+
+ /* And fill in the fields */
+ curr->timestamp = now;
+ curr->src_addr = addr;
+ curr->dest_addr.s_addr = ip_hdr->daddr;
+ curr->src_port = src_port;
+ curr->count = 1;
+ curr->weight = (ntohs(dest_port) < 1024) ?
+ psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
+ curr->ports[0].number = dest_port;
+ curr->ports[0].proto = proto;
+ curr->ports[0].and_flags = tcp_flags;
+ curr->ports[0].or_flags = tcp_flags;
+ curr->tos = ip_hdr->tos;
+ curr->ttl = ip_hdr->ttl;
+
+out_no_match:
+ spin_unlock(&state.lock);
+ return 0;
+
+out_match:
+ spin_unlock(&state.lock);
+ return 1;
+}
+
+static int ipt_psd_checkentry(const char *tablename,
+ const struct ipt_ip *e,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+/* const struct ipt_psd_info *psdinfo = targinfo;*/
+
+ /* we accept TCP only */
+/* if (e->ip.proto != IPPROTO_TCP) { */
+/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
+/* return 0; */
+/* } */
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
+ DEBUGP("PSD: matchsize %u != %u\n",
+ matchsize,
+ IPT_ALIGN(sizeof(struct ipt_psd_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_match ipt_psd_reg = {
+ .name = "psd",
+ .match = ipt_psd_match,
+ .checkentry = ipt_psd_checkentry,
+ .me = THIS_MODULE };
+
+static int __init init(void)
+{
+ if (ipt_register_match(&ipt_psd_reg))
+ return -EINVAL;
+
+ memset(&state, 0, sizeof(state));
+
+ spin_lock_init(&(state.lock));
+
+ printk("netfilter PSD loaded - (c) astaro AG\n");
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&ipt_psd_reg);
+ printk("netfilter PSD unloaded - (c) astaro AG\n");
+}
+
+module_init(init);
+module_exit(fini);
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_psd.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_PSD_H
+#define _IPT_PSD_H
+
+#include <linux/param.h>
+#include <linux/types.h>
+
+/*
+ * High port numbers have a lower weight to reduce the frequency of false
+ * positives, such as from passive mode FTP transfers.
+ */
+#define PORT_WEIGHT_PRIV 3
+#define PORT_WEIGHT_HIGH 1
+
+/*
+ * Port scan detection thresholds: at least COUNT ports need to be scanned
+ * from the same source, with no longer than DELAY ticks between ports.
+ */
+#define SCAN_MIN_COUNT 7
+#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
+#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
+#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
+
+/*
+ * Keep track of up to LIST_SIZE source addresses, using a hash table of
+ * HASH_SIZE entries for faster lookups, but limiting hash collisions to
+ * HASH_MAX source addresses per the same hash value.
+ */
+#define LIST_SIZE 0x100
+#define HASH_LOG 9
+#define HASH_SIZE (1 << HASH_LOG)
+#define HASH_MAX 0x10
+
+struct ipt_psd_info {
+ unsigned int weight_threshold;
+ unsigned int delay_threshold;
+ unsigned short lo_ports_weight;
+ unsigned short hi_ports_weight;
+};
+
+#endif /*_IPT_PSD_H*/
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -49,6 +49,7 @@
# matches
obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
+obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
# targets

View File

@ -0,0 +1,190 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: netfilter: Implement RFC 1123 for FTP conntrack
References: bnc#466279 bnc#681639
Patch-mainline: Submitted via http://bugzilla.netfilter.org/show_bug.cgi?id=574 23 Jan 2011
The FTP conntrack code currently only accepts the following format for
the 227 response for PASV:
227 Entering Passive Mode (148,100,81,40,31,161).
It doesn't accept the following format from an obscure server:
227 Data transfer will passively listen to 67,218,99,134,50,144
From RFC 1123:
The format of the 227 reply to a PASV command is not
well standardized. In particular, an FTP client cannot
assume that the parentheses shown on page 40 of RFC-959
will be present (and in fact, Figure 3 on page 43 omits
them). Therefore, a User-FTP program that interprets
the PASV reply must scan the reply for the first digit
of the host and port numbers.
This patch adds support for the RFC 1123 clarification by:
- Allowing a search filter to specify NUL as the terminator so that
try_number will return successfully if the array of numbers has been
filled when an unexpected character is encountered.
- Using space as the separator for the 227 reply and then scanning for
the first digit of the number sequence. The number sequence is parsed
out using the existing try_rfc959 but with a NUL terminator.
Tracked in: https://bugzilla.novell.com/show_bug.cgi?id=466279
Reported-by: Mark Post <mpost@novell.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
net/netfilter/nf_conntrack_ftp.c | 73 ++++++++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 19 deletions(-)
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -53,10 +53,14 @@ unsigned int (*nf_nat_ftp_hook)(struct s
struct nf_conntrack_expect *exp);
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
-static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
-static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
+static int try_rfc959(const char *, size_t, struct nf_conntrack_man *,
+ char, unsigned int *);
+static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *,
+ char, unsigned int *);
+static int try_eprt(const char *, size_t, struct nf_conntrack_man *,
+ char, unsigned int *);
static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
- char);
+ char, unsigned int *);
static struct ftp_search {
const char *pattern;
@@ -64,7 +68,7 @@ static struct ftp_search {
char skip;
char term;
enum nf_ct_ftp_type ftptype;
- int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
+ int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char, unsigned int *);
} search[IP_CT_DIR_MAX][2] = {
[IP_CT_DIR_ORIGINAL] = {
{
@@ -88,10 +92,8 @@ static struct ftp_search {
{
.pattern = "227 ",
.plen = sizeof("227 ") - 1,
- .skip = '(',
- .term = ')',
.ftptype = NF_CT_FTP_PASV,
- .getnum = try_rfc959,
+ .getnum = try_rfc1123,
},
{
.pattern = "229 ",
@@ -130,8 +132,9 @@ static int try_number(const char *data,
i++;
else {
/* Unexpected character; true if it's the
- terminator and we're finished. */
- if (*data == term && i == array_size - 1)
+ terminator (or we don't care about one)
+ and we're finished. */
+ if ((*data == term || !term) && i == array_size - 1)
return len;
pr_debug("Char %u (got %u nums) `%u' unexpected\n",
@@ -146,7 +149,8 @@ static int try_number(const char *data,
/* Returns 0, or length of numbers: 192,168,1,1,5,6 */
static int try_rfc959(const char *data, size_t dlen,
- struct nf_conntrack_man *cmd, char term)
+ struct nf_conntrack_man *cmd, char term,
+ unsigned int *offset)
{
int length;
u_int32_t array[6];
@@ -161,6 +165,33 @@ static int try_rfc959(const char *data,
return length;
}
+/*
+ * From RFC 1123:
+ * The format of the 227 reply to a PASV command is not
+ * well standardized. In particular, an FTP client cannot
+ * assume that the parentheses shown on page 40 of RFC-959
+ * will be present (and in fact, Figure 3 on page 43 omits
+ * them). Therefore, a User-FTP program that interprets
+ * the PASV reply must scan the reply for the first digit
+ * of the host and port numbers.
+ */
+static int try_rfc1123(const char *data, size_t dlen,
+ struct nf_conntrack_man *cmd, char term,
+ unsigned int *offset)
+{
+ int i;
+ for (i = 0; i < dlen; i++)
+ if (isdigit(data[i]))
+ break;
+
+ if (i == dlen)
+ return 0;
+
+ *offset += i;
+
+ return try_rfc959(data + i, dlen - i, cmd, 0, offset);
+}
+
/* Grab port: number up to delimiter */
static int get_port(const char *data, int start, size_t dlen, char delim,
__be16 *port)
@@ -189,7 +220,7 @@ static int get_port(const char *data, in
/* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */
static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
- char term)
+ char term, unsigned int *offset)
{
char delim;
int length;
@@ -237,7 +268,8 @@ static int try_eprt(const char *data, si
/* Returns 0, or length of numbers: |||6446| */
static int try_epsv_response(const char *data, size_t dlen,
- struct nf_conntrack_man *cmd, char term)
+ struct nf_conntrack_man *cmd, char term,
+ unsigned int *offset)
{
char delim;
@@ -259,9 +291,10 @@ static int find_pattern(const char *data
unsigned int *numlen,
struct nf_conntrack_man *cmd,
int (*getnum)(const char *, size_t,
- struct nf_conntrack_man *, char))
+ struct nf_conntrack_man *, char,
+ unsigned int *))
{
- size_t i;
+ size_t i = plen;
pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
if (dlen == 0)
@@ -291,16 +324,18 @@ static int find_pattern(const char *data
pr_debug("Pattern matches!\n");
/* Now we've found the constant string, try to skip
to the 'skip' character */
- for (i = plen; data[i] != skip; i++)
- if (i == dlen - 1) return -1;
+ if (skip) {
+ for (i = plen; data[i] != skip; i++)
+ if (i == dlen - 1) return -1;
- /* Skip over the last character */
- i++;
+ /* Skip over the last character */
+ i++;
+ }
pr_debug("Skipped up to `%c'!\n", skip);
*numoff = i;
- *numlen = getnum(data + i, dlen - i, cmd, term);
+ *numlen = getnum(data + i, dlen - i, cmd, term, numoff);
if (!*numlen)
return -1;

View File

@ -0,0 +1,185 @@
From: Jiri Bohac <jbohac@suse.cz>
Subject: connection tracking helper for SLP
References: fate#301134
Patch-mainline: Not yet
A simple connection tracking helper for SLP. Marks replies to a
SLP broadcast query as ESTABLISHED to allow them to pass through the
firewall.
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
---
net/netfilter/Kconfig | 15 ++++
net/netfilter/Makefile | 1
net/netfilter/nf_conntrack_slp.c | 131 +++++++++++++++++++++++++++++++++++++++
3 files changed, 147 insertions(+)
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -290,6 +290,21 @@ config NF_CONNTRACK_TFTP
To compile it as a module, choose M here. If unsure, say N.
+config NF_CONNTRACK_SLP
+ tristate "SLP protocol support"
+ depends on NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
+ help
+ SLP queries are sometimes sent as broadcast messages from an
+ unprivileged port and responded to with unicast messages to the
+ same port. This make them hard to firewall properly because connection
+ tracking doesn't deal with broadcasts. This helper tracks locally
+ originating broadcast SLP queries and the corresponding
+ responses. It relies on correct IP address configuration, specifically
+ netmask and broadcast address.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NF_CT_NETLINK
tristate 'Connection tracking netlink interface'
select NETFILTER_NETLINK
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co
obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
+obj-$(CONFIG_NF_CONNTRACK_SLP) += nf_conntrack_slp.o
# transparent proxy support
obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
--- /dev/null
+++ b/net/netfilter/nf_conntrack_slp.c
@@ -0,0 +1,131 @@
+/*
+ * NetBIOS name service broadcast connection tracking helper
+ *
+ * (c) 2007 Jiri Bohac <jbohac@suse.cz>
+ * (c) 2005 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+/*
+ * This helper tracks locally originating NetBIOS name service
+ * requests by issuing permanent expectations (valid until
+ * timing out) matching all reply connections from the
+ * destination network. The only NetBIOS specific thing is
+ * actually the port number.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/if_addr.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <net/route.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#define SLP_PORT 427
+
+MODULE_AUTHOR("Jiri Bohac <jbohac@suse.cz>");
+MODULE_DESCRIPTION("SLP broadcast connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ip_conntrack_slp");
+
+static unsigned int timeout __read_mostly = 3;
+module_param(timeout, uint, 0400);
+MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
+
+static int help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ struct nf_conntrack_expect *exp;
+ struct rtable *rt = skb_rtable(skb);
+ struct in_device *in_dev;
+ __be32 mask = 0;
+ __be32 src = 0;
+
+ /* we're only interested in locally generated packets */
+ if (skb->sk == NULL)
+ goto out;
+ if (rt == NULL || !(rt->rt_flags & (RTCF_MULTICAST|RTCF_BROADCAST)))
+ goto out;
+ if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+ goto out;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(rt->dst.dev);
+ if (in_dev != NULL) {
+ for_primary_ifa(in_dev) {
+ /* this is a hack as slp uses multicast we can't match
+ * the destination address to some broadcast address. So
+ * just take the first one. Better would be to install
+ * expectations for all addresses */
+ mask = ifa->ifa_mask;
+ src = ifa->ifa_broadcast;
+ break;
+ } endfor_ifa(in_dev);
+ }
+ rcu_read_unlock();
+
+ if (mask == 0 || src == 0)
+ goto out;
+
+ exp = nf_ct_expect_alloc(ct);
+ if (exp == NULL)
+ goto out;
+
+ exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ exp->tuple.src.u3.ip = src;
+ exp->tuple.src.u.udp.port = htons(SLP_PORT);
+
+ exp->mask.src.u3.ip = mask;
+ exp->mask.src.u.udp.port = htons(0xFFFF);
+
+ exp->expectfn = NULL;
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+ exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
+ exp->helper = NULL;
+
+ nf_ct_expect_related(exp);
+ nf_ct_expect_put(exp);
+
+ nf_ct_refresh(ct, skb, timeout * HZ);
+out:
+ return NF_ACCEPT;
+}
+
+static struct nf_conntrack_expect_policy exp_policy = {
+ .max_expected = 1,
+};
+
+static struct nf_conntrack_helper helper __read_mostly = {
+ .name = "slp",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(SLP_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ .help = help,
+ .expect_policy = &exp_policy,
+};
+
+static int __init nf_conntrack_slp_init(void)
+{
+ exp_policy.timeout = timeout;
+ return nf_conntrack_helper_register(&helper);
+}
+
+static void __exit nf_conntrack_slp_fini(void)
+{
+ nf_conntrack_helper_unregister(&helper);
+}
+
+module_init(nf_conntrack_slp_init);
+module_exit(nf_conntrack_slp_fini);

View File

@ -0,0 +1,39 @@
From c83e5a977a2510de872d48a4d3bebc94dac0ed8f Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Fri, 13 May 2011 16:01:39 -0700
Subject: [PATCH 2/2] btrfs: Introduce btrfs_get_maps_dev()
References: bnc#672923
Patch-mainline: Never
Use this to return the subvolume superblock in proc instead of the global
superblock which is automatically taken today. This fixes a userspace
breakage where discrepancies between the devices two would confuse software
such as lsof.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
fs/btrfs/super.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1301,6 +1301,11 @@ static void btrfs_fs_dirty_inode(struct
"error %d\n", btrfs_ino(inode), ret);
}
+static dev_t btrfs_get_maps_dev(struct inode *inode)
+{
+ return BTRFS_I(inode)->root->anon_dev;
+}
+
static const struct super_operations btrfs_super_ops = {
.drop_inode = btrfs_drop_inode,
.evict_inode = btrfs_evict_inode,
@@ -1315,6 +1320,7 @@ static const struct super_operations btr
.remount_fs = btrfs_remount,
.freeze_fs = btrfs_freeze,
.unfreeze_fs = btrfs_unfreeze,
+ .get_maps_dev = btrfs_get_maps_dev,
};
static const struct file_operations btrfs_ctl_fops = {

View File

@ -0,0 +1,304 @@
From: Josef Bacik <josef@redhat.com>
Date: Thu, 10 Nov 2011 08:29:20 -0500
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] Btrfs: add allocator tracepoints
I used these tracepoints when figuring out what the cluster stuff was doing, so
add them to mainline in case we need to profile this stuff again. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/extent-tree.c | 9 ++
fs/btrfs/free-space-cache.c | 11 ++
include/trace/events/btrfs.h | 173 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 192 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5128,6 +5128,8 @@
ins->objectid = 0;
ins->offset = 0;
+ trace_find_free_extent(orig_root, num_bytes, empty_size, data);
+
space_info = __find_space_info(root->fs_info, data);
if (!space_info) {
printk(KERN_ERR "No space info for %llu\n", data);
@@ -5313,6 +5315,8 @@
if (offset) {
/* we have a block, we're done */
spin_unlock(&last_ptr->refill_lock);
+ trace_btrfs_reserve_extent_cluster(root,
+ block_group, search_start, num_bytes);
goto checks;
}
@@ -5359,6 +5363,9 @@
if (offset) {
/* we found one, proceed */
spin_unlock(&last_ptr->refill_lock);
+ trace_btrfs_reserve_extent_cluster(root,
+ block_group, search_start,
+ num_bytes);
goto checks;
}
} else if (!cached && loop > LOOP_CACHING_NOWAIT
@@ -5439,6 +5446,8 @@
ins->objectid = search_start;
ins->offset = num_bytes;
+ trace_btrfs_reserve_extent(orig_root, block_group,
+ search_start, num_bytes);
if (offset < search_start)
btrfs_add_free_space(used_block_group, offset,
search_start - offset);
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2346,6 +2346,8 @@
&entry->offset_index, 1);
BUG_ON(ret);
+ trace_btrfs_setup_cluster(block_group, cluster,
+ total_found * block_group->sectorsize, 1);
return 0;
}
@@ -2368,6 +2370,7 @@
u64 window_free;
u64 max_extent;
u64 max_gap = 128 * 1024;
+ u64 total_size = 0;
entry = tree_search_offset(ctl, offset, 0, 1);
if (!entry)
@@ -2444,11 +2447,12 @@
rb_erase(&entry->offset_index, &ctl->free_space_offset);
ret = tree_insert_offset(&cluster->root, entry->offset,
&entry->offset_index, 0);
+ total_size += entry->bytes;
BUG_ON(ret);
} while (node && entry != last);
cluster->max_size = max_extent;
-
+ trace_btrfs_setup_cluster(block_group, cluster, total_size, 0);
return 0;
}
@@ -2552,6 +2556,9 @@
goto out;
}
+ trace_btrfs_find_cluster(block_group, offset, bytes, empty_size,
+ min_bytes);
+
ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
bytes, min_bytes);
if (ret)
@@ -2567,6 +2574,8 @@
list_add_tail(&cluster->block_group_list,
&block_group->cluster_list);
cluster->block_group = block_group;
+ } else {
+ trace_btrfs_failed_cluster_setup(block_group);
}
out:
spin_unlock(&cluster->lock);
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -16,6 +16,8 @@
struct btrfs_delayed_tree_ref;
struct btrfs_delayed_data_ref;
struct btrfs_delayed_ref_head;
+struct btrfs_block_group_cache;
+struct btrfs_free_cluster;
struct map_lookup;
struct extent_buffer;
@@ -44,6 +46,15 @@
obj, ((obj >= BTRFS_DATA_RELOC_TREE_OBJECTID) || \
(obj <= BTRFS_CSUM_TREE_OBJECTID )) ? __show_root_type(obj) : "-"
+#define BTRFS_GROUP_FLAGS \
+ { BTRFS_BLOCK_GROUP_DATA, "DATA"}, \
+ { BTRFS_BLOCK_GROUP_SYSTEM, "SYSTEM"}, \
+ { BTRFS_BLOCK_GROUP_METADATA, "METADATA"}, \
+ { BTRFS_BLOCK_GROUP_RAID0, "RAID0"}, \
+ { BTRFS_BLOCK_GROUP_RAID1, "RAID1"}, \
+ { BTRFS_BLOCK_GROUP_DUP, "DUP"}, \
+ { BTRFS_BLOCK_GROUP_RAID10, "RAID10"}
+
TRACE_EVENT(btrfs_transaction_commit,
TP_PROTO(struct btrfs_root *root),
@@ -661,6 +672,168 @@
TP_ARGS(root, start, len)
);
+TRACE_EVENT(find_free_extent,
+
+ TP_PROTO(struct btrfs_root *root, u64 num_bytes, u64 empty_size,
+ u64 data),
+
+ TP_ARGS(root, num_bytes, empty_size, data),
+
+ TP_STRUCT__entry(
+ __field( u64, root_objectid )
+ __field( u64, num_bytes )
+ __field( u64, empty_size )
+ __field( u64, data )
+ ),
+
+ TP_fast_assign(
+ __entry->root_objectid = root->root_key.objectid;
+ __entry->num_bytes = num_bytes;
+ __entry->empty_size = empty_size;
+ __entry->data = data;
+ ),
+
+ TP_printk("root = %Lu(%s), len = %Lu, empty_size = %Lu, "
+ "flags = %Lu(%s)", show_root_type(__entry->root_objectid),
+ __entry->num_bytes, __entry->empty_size, __entry->data,
+ __print_flags((unsigned long)__entry->data, "|",
+ BTRFS_GROUP_FLAGS))
+);
+
+DECLARE_EVENT_CLASS(btrfs__reserve_extent,
+
+ TP_PROTO(struct btrfs_root *root,
+ struct btrfs_block_group_cache *block_group, u64 start,
+ u64 len),
+
+ TP_ARGS(root, block_group, start, len),
+
+ TP_STRUCT__entry(
+ __field( u64, root_objectid )
+ __field( u64, bg_objectid )
+ __field( u64, flags )
+ __field( u64, start )
+ __field( u64, len )
+ ),
+
+ TP_fast_assign(
+ __entry->root_objectid = root->root_key.objectid;
+ __entry->bg_objectid = block_group->key.objectid;
+ __entry->flags = block_group->flags;
+ __entry->start = start;
+ __entry->len = len;
+ ),
+
+ TP_printk("root = %Lu(%s), block_group = %Lu, flags = %Lu(%s), "
+ "start = %Lu, len = %Lu",
+ show_root_type(__entry->root_objectid), __entry->bg_objectid,
+ __entry->flags, __print_flags((unsigned long)__entry->flags,
+ "|", BTRFS_GROUP_FLAGS),
+ __entry->start, __entry->len)
+);
+
+DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent,
+
+ TP_PROTO(struct btrfs_root *root,
+ struct btrfs_block_group_cache *block_group, u64 start,
+ u64 len),
+
+ TP_ARGS(root, block_group, start, len)
+);
+
+DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster,
+
+ TP_PROTO(struct btrfs_root *root,
+ struct btrfs_block_group_cache *block_group, u64 start,
+ u64 len),
+
+ TP_ARGS(root, block_group, start, len)
+);
+
+TRACE_EVENT(btrfs_find_cluster,
+
+ TP_PROTO(struct btrfs_block_group_cache *block_group, u64 start,
+ u64 bytes, u64 empty_size, u64 min_bytes),
+
+ TP_ARGS(block_group, start, bytes, empty_size, min_bytes),
+
+ TP_STRUCT__entry(
+ __field( u64, bg_objectid )
+ __field( u64, flags )
+ __field( u64, start )
+ __field( u64, bytes )
+ __field( u64, empty_size )
+ __field( u64, min_bytes )
+ ),
+
+ TP_fast_assign(
+ __entry->bg_objectid = block_group->key.objectid;
+ __entry->flags = block_group->flags;
+ __entry->start = start;
+ __entry->bytes = bytes;
+ __entry->empty_size = empty_size;
+ __entry->min_bytes = min_bytes;
+ ),
+
+ TP_printk("block_group = %Lu, flags = %Lu(%s), start = %Lu, len = %Lu,"
+ " empty_size = %Lu, min_bytes = %Lu", __entry->bg_objectid,
+ __entry->flags,
+ __print_flags((unsigned long)__entry->flags, "|",
+ BTRFS_GROUP_FLAGS), __entry->start,
+ __entry->bytes, __entry->empty_size, __entry->min_bytes)
+);
+
+TRACE_EVENT(btrfs_failed_cluster_setup,
+
+ TP_PROTO(struct btrfs_block_group_cache *block_group),
+
+ TP_ARGS(block_group),
+
+ TP_STRUCT__entry(
+ __field( u64, bg_objectid )
+ ),
+
+ TP_fast_assign(
+ __entry->bg_objectid = block_group->key.objectid;
+ ),
+
+ TP_printk("block_group = %Lu", __entry->bg_objectid)
+);
+
+TRACE_EVENT(btrfs_setup_cluster,
+
+ TP_PROTO(struct btrfs_block_group_cache *block_group,
+ struct btrfs_free_cluster *cluster, u64 size, int bitmap),
+
+ TP_ARGS(block_group, cluster, size, bitmap),
+
+ TP_STRUCT__entry(
+ __field( u64, bg_objectid )
+ __field( u64, flags )
+ __field( u64, start )
+ __field( u64, max_size )
+ __field( u64, size )
+ __field( int, bitmap )
+ ),
+
+ TP_fast_assign(
+ __entry->bg_objectid = block_group->key.objectid;
+ __entry->flags = block_group->flags;
+ __entry->start = cluster->window_start;
+ __entry->max_size = cluster->max_size;
+ __entry->size = size;
+ __entry->bitmap = bitmap;
+ ),
+
+ TP_printk("block_group = %Lu, flags = %Lu(%s), window_start = %Lu, "
+ "size = %Lu, max_size = %Lu, bitmap = %d",
+ __entry->bg_objectid,
+ __entry->flags,
+ __print_flags((unsigned long)__entry->flags, "|",
+ BTRFS_GROUP_FLAGS), __entry->start,
+ __entry->size, __entry->max_size, __entry->bitmap)
+);
+
#endif /* _TRACE_BTRFS_H */
/* This part must be outside protection */

View File

@ -0,0 +1,299 @@
From 033eea6d488471c7262b377e066ecf9eea85d5b1 Mon Sep 17 00:00:00 2001
From: Li Zefan <lizf@cn.fujitsu.com>
Date: Thu, 17 Nov 2011 15:26:17 +0800
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] Btrfs: rewrite btrfs_trim_block_group()
There are various bugs in block group trimming:
- It may trim from offset smaller than user-specified offset.
- It may trim beyond user-specified range.
- It may leak free space for extents smaller than specified minlen.
- It may truncate the last trimmed extent thus leak free space.
- With mixed extents+bitmaps, some extents may not be trimmed.
- With mixed extents+bitmaps, some bitmaps may not be trimmed (even
none will be trimmed). Even for those trimmed, not all the free space
in the bitmaps will be trimmed.
I rewrite btrfs_trim_block_group() and break it into two functions.
One is to trim extents only, and the other is to trim bitmaps only.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/free-space-cache.c | 233 ++++++++++++++++++++++++++++++--------------
1 file changed, 163 insertions(+), 70 deletions(-)
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2586,17 +2586,57 @@ void btrfs_init_free_cluster(struct btrf
cluster->block_group = NULL;
}
-int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
- u64 *trimmed, u64 start, u64 end, u64 minlen)
+static int do_trimming(struct btrfs_block_group_cache *block_group,
+ u64 *total_trimmed, u64 start, u64 bytes,
+ u64 reserved_start, u64 reserved_bytes)
{
- struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
- struct btrfs_free_space *entry = NULL;
+ struct btrfs_space_info *space_info = block_group->space_info;
struct btrfs_fs_info *fs_info = block_group->fs_info;
- u64 bytes = 0;
- u64 actually_trimmed;
- int ret = 0;
+ int ret;
+ int update = 0;
+ u64 trimmed = 0;
+
+ spin_lock(&space_info->lock);
+ spin_lock(&block_group->lock);
+ if (!block_group->ro) {
+ block_group->reserved += reserved_bytes;
+ space_info->bytes_reserved += reserved_bytes;
+ update = 1;
+ }
+ spin_unlock(&block_group->lock);
+ spin_unlock(&space_info->lock);
- *trimmed = 0;
+ ret = btrfs_error_discard_extent(fs_info->extent_root,
+ start, bytes, &trimmed);
+ if (!ret)
+ *total_trimmed += trimmed;
+
+ btrfs_add_free_space(block_group, reserved_start, reserved_bytes);
+
+ if (update) {
+ spin_lock(&space_info->lock);
+ spin_lock(&block_group->lock);
+ if (block_group->ro)
+ space_info->bytes_readonly += reserved_bytes;
+ block_group->reserved -= reserved_bytes;
+ space_info->bytes_reserved -= reserved_bytes;
+ spin_unlock(&space_info->lock);
+ spin_unlock(&block_group->lock);
+ }
+
+ return ret;
+}
+
+static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
+ u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+{
+ struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+ struct btrfs_free_space *entry;
+ struct rb_node *node;
+ int ret = 0;
+ u64 extent_start;
+ u64 extent_bytes;
+ u64 bytes;
while (start < end) {
spin_lock(&ctl->tree_lock);
@@ -2607,81 +2647,118 @@ int btrfs_trim_block_group(struct btrfs_
}
entry = tree_search_offset(ctl, start, 0, 1);
- if (!entry)
- entry = tree_search_offset(ctl,
- offset_to_bitmap(ctl, start),
- 1, 1);
-
- if (!entry || entry->offset >= end) {
+ if (!entry) {
spin_unlock(&ctl->tree_lock);
break;
}
- if (entry->bitmap) {
- ret = search_bitmap(ctl, entry, &start, &bytes);
- if (!ret) {
- if (start >= end) {
- spin_unlock(&ctl->tree_lock);
- break;
- }
- bytes = min(bytes, end - start);
- bitmap_clear_bits(ctl, entry, start, bytes);
- if (entry->bytes == 0)
- free_bitmap(ctl, entry);
- } else {
- start = entry->offset + BITS_PER_BITMAP *
- block_group->sectorsize;
+ /* skip bitmaps */
+ while (entry->bitmap) {
+ node = rb_next(&entry->offset_index);
+ if (!node) {
spin_unlock(&ctl->tree_lock);
- ret = 0;
- continue;
+ goto out;
}
- } else {
- start = entry->offset;
- bytes = min(entry->bytes, end - start);
- unlink_free_space(ctl, entry);
- kmem_cache_free(btrfs_free_space_cachep, entry);
+ entry = rb_entry(node, struct btrfs_free_space,
+ offset_index);
+ }
+
+ if (entry->offset >= end) {
+ spin_unlock(&ctl->tree_lock);
+ break;
}
+ extent_start = entry->offset;
+ extent_bytes = entry->bytes;
+ start = max(start, extent_start);
+ bytes = min(extent_start + extent_bytes, end) - start;
+ if (bytes < minlen) {
+ spin_unlock(&ctl->tree_lock);
+ goto next;
+ }
+
+ unlink_free_space(ctl, entry);
+ kmem_cache_free(btrfs_free_space_cachep, entry);
+
spin_unlock(&ctl->tree_lock);
- if (bytes >= minlen) {
- struct btrfs_space_info *space_info;
- int update = 0;
-
- space_info = block_group->space_info;
- spin_lock(&space_info->lock);
- spin_lock(&block_group->lock);
- if (!block_group->ro) {
- block_group->reserved += bytes;
- space_info->bytes_reserved += bytes;
- update = 1;
- }
- spin_unlock(&block_group->lock);
- spin_unlock(&space_info->lock);
+ ret = do_trimming(block_group, total_trimmed, start, bytes,
+ extent_start, extent_bytes);
+ if (ret)
+ break;
+next:
+ start += bytes;
- ret = btrfs_error_discard_extent(fs_info->extent_root,
- start,
- bytes,
- &actually_trimmed);
-
- btrfs_add_free_space(block_group, start, bytes);
- if (update) {
- spin_lock(&space_info->lock);
- spin_lock(&block_group->lock);
- if (block_group->ro)
- space_info->bytes_readonly += bytes;
- block_group->reserved -= bytes;
- space_info->bytes_reserved -= bytes;
- spin_unlock(&space_info->lock);
- spin_unlock(&block_group->lock);
- }
+ if (fatal_signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ cond_resched();
+ }
+out:
+ return ret;
+}
+
+static int trim_bitmaps(struct btrfs_block_group_cache *block_group,
+ u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+{
+ struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+ struct btrfs_free_space *entry;
+ int ret = 0;
+ int ret2;
+ u64 bytes;
+ u64 offset = offset_to_bitmap(ctl, start);
+
+ while (offset < end) {
+ bool next_bitmap = false;
+
+ spin_lock(&ctl->tree_lock);
- if (ret)
- break;
- *trimmed += actually_trimmed;
+ if (ctl->free_space < minlen) {
+ spin_unlock(&ctl->tree_lock);
+ break;
+ }
+
+ entry = tree_search_offset(ctl, offset, 1, 0);
+ if (!entry) {
+ spin_unlock(&ctl->tree_lock);
+ next_bitmap = true;
+ goto next;
+ }
+
+ bytes = minlen;
+ ret2 = search_bitmap(ctl, entry, &start, &bytes);
+ if (ret2 || start >= end) {
+ spin_unlock(&ctl->tree_lock);
+ next_bitmap = true;
+ goto next;
+ }
+
+ bytes = min(bytes, end - start);
+ if (bytes < minlen) {
+ spin_unlock(&ctl->tree_lock);
+ goto next;
+ }
+
+ bitmap_clear_bits(ctl, entry, start, bytes);
+ if (entry->bytes == 0)
+ free_bitmap(ctl, entry);
+
+ spin_unlock(&ctl->tree_lock);
+
+ ret = do_trimming(block_group, total_trimmed, start, bytes,
+ start, bytes);
+ if (ret)
+ break;
+next:
+ if (next_bitmap) {
+ offset += BITS_PER_BITMAP * ctl->unit;
+ } else {
+ start += bytes;
+ if (start >= offset + BITS_PER_BITMAP * ctl->unit)
+ offset += BITS_PER_BITMAP * ctl->unit;
}
- start += bytes;
- bytes = 0;
if (fatal_signal_pending(current)) {
ret = -ERESTARTSYS;
@@ -2693,6 +2770,22 @@ int btrfs_trim_block_group(struct btrfs_
return ret;
}
+
+int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
+ u64 *trimmed, u64 start, u64 end, u64 minlen)
+{
+ int ret;
+
+ *trimmed = 0;
+
+ ret = trim_no_bitmap(block_group, trimmed, start, end, minlen);
+ if (ret)
+ return ret;
+
+ ret = trim_bitmaps(block_group, trimmed, start, end, minlen);
+
+ return ret;
+}
/*
* Find the left-most item in the cache tree, and then return the

View File

@ -0,0 +1,40 @@
From e2049e28add8f8fbfa8680fcf5fc49fa3b713ceb Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Tue, 22 Nov 2011 18:05:48 +0100
Patch-mainline: pending
References: FATE#306586 bnc#730103
Subject: [PATCH] btrfs: lock and disable irq during space alloc
This is a workaround.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/free-space-cache.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 7807276..e49c1cd 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2102,7 +2102,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
u64 bytes_search = bytes + empty_size;
u64 ret = 0;
- spin_lock(&ctl->tree_lock);
+ spin_lock_irq(&ctl->tree_lock);
entry = find_free_space(ctl, &offset, &bytes_search);
if (!entry)
goto out;
@@ -2123,7 +2123,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
}
out:
- spin_unlock(&ctl->tree_lock);
+ spin_unlock_irq(&ctl->tree_lock);
return ret;
}
--
1.7.6

View File

@ -0,0 +1,43 @@
From: Keith Mannthey <kmannth@us.ibm.com>
Date: Tue, 29 Nov 2011 17:44:12 -0800
Patch-mainline: pending
References: FATE#306586 bnc#724620
Subject: [PATCH] Sector Size check during Mount
Gracefully fail when trying to mount a BTRFS file system that has a
sectorsize smaller than PAGE_SIZE.
On PPC it is possible to build a FS while using a 4k PAGE_SIZE kernel
then boot into a 64K PAGE_SIZE kernel. Presently open_ctree fails in an
endless loop and hangs the machine in this situation.
My debugging has show this Sector size < Page size to be a non trivial
situation and a graceful exit from the situation would be nice for the
time being.
Signed-off-by: Keith Mannthey <kmannth@us.ibm.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/disk-io.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 94abc25..1cbfa75 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2230,6 +2230,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,
goto fail_sb_buffer;
}
+ if (sectorsize < PAGE_SIZE) {
+ printk(KERN_WARNING "btrfs: Incompatible sector size "
+ "found on %s\n", sb->s_id);
+ goto fail_sb_buffer;
+ }
+
mutex_lock(&fs_info->chunk_mutex);
ret = btrfs_read_sys_array(tree_root);
mutex_unlock(&fs_info->chunk_mutex);
--
1.7.6.233.gd79bc

View File

@ -0,0 +1,158 @@
From: David Sterba <dsterba@suse.cz>
Date: Tue, 28 Jun 2011 12:38:06 +0200
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] btrfs: add new ioctl to determine size of compressed file
Go through all extents of a file in a given [start,end) range and sum
for:
* regular extent: ->block_len, size is already rounded up to blocks
* inline extents: length rounded up to 512
The range is start inclusive / end exclusive. For whole a file pass
0 and (u64)-1.
The values returned are number of occupied 512B sectors for uncompressed
and compressed size and can be easily compared to determine rough
compression ratio of the given file range.
Based on implementation from Ulrich Hecht,
http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ioctl.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/btrfs/ioctl.h | 12 ++++++++
2 files changed, 95 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c04f02c..91e6ab8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2972,6 +2972,86 @@ static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
return 0;
}
+/*
+ * Returns the compressed size of an inode in 512 byte blocks.
+ * Count the on-disk space used by extents starting in range [start, end),
+ * inline data are rounded up to sector, ie. 512.
+ *
+ * The range is start inclusive and end exclusive so it can be used to
+ * determine compressed size of a given extent by its start and start of the
+ * next extent easily, without counting length.
+ * Whole file is specified as start = 0, end = (u64)-1
+ */
+static long btrfs_ioctl_compr_size(struct file *file, void __user *argp)
+{
+ struct inode *inode = fdentry(file)->d_inode;
+ struct btrfs_ioctl_compr_size_args compr_args;
+ u64 len;
+ u64 compressed_size = 0;
+ u64 size = 0;
+ u64 offset = 0;
+
+ if (S_ISDIR(inode->i_mode))
+ return -EISDIR;
+
+ if (copy_from_user(&compr_args, argp,
+ sizeof(struct btrfs_ioctl_compr_size_args)))
+ return -EFAULT;
+
+ if (compr_args.start > compr_args.end)
+ return -EINVAL;
+
+ mutex_lock(&inode->i_mutex);
+
+ offset = compr_args.start;
+ if (inode->i_size > compr_args.end)
+ len = compr_args.end;
+ else
+ len = inode->i_size;
+
+ /*
+ * do any pending delalloc/csum calc on inode, one way or
+ * another, and lock file content
+ */
+ btrfs_wait_ordered_range(inode, compr_args.start, len);
+
+ lock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS);
+
+ while (offset < len) {
+ struct extent_map *em;
+
+ em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0);
+ if (IS_ERR_OR_NULL(em))
+ goto error;
+ if (em->block_len != (u64)-1) {
+ compressed_size += em->block_len;
+ size += ALIGN(em->len, inode->i_sb->s_blocksize);
+ } else if (em->block_start == EXTENT_MAP_INLINE) {
+ compressed_size += ALIGN(em->len, 512);
+ size += ALIGN(em->len, 512);
+ }
+ offset += em->len;
+ free_extent_map(em);
+ }
+ unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS);
+ mutex_unlock(&inode->i_mutex);
+
+ compr_args.size = size >> 9;
+ compr_args.compressed_size = compressed_size >> 9;
+
+ if (copy_to_user(argp, &compr_args,
+ sizeof(struct btrfs_ioctl_compr_size_args)))
+ return -EFAULT;
+
+ return 0;
+
+error:
+ unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS);
+ mutex_unlock(&inode->i_mutex);
+
+ return -EIO;
+}
+
static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
void __user *arg)
{
@@ -3110,6 +3190,8 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_scrub_cancel(root, argp);
case BTRFS_IOC_SCRUB_PROGRESS:
return btrfs_ioctl_scrub_progress(root, argp);
+ case BTRFS_IOC_COMPR_SIZE:
+ return btrfs_ioctl_compr_size(file, argp);
}
return -ENOTTY;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -217,6 +217,16 @@ struct btrfs_ioctl_logical_ino_args {
__u64 inodes;
};
+struct btrfs_ioctl_compr_size_args {
+ /* Range start, inclusive */
+ __u64 start; /* in */
+ /* Range end, exclusive */
+ __u64 end; /* in */
+ __u64 size; /* out */
+ __u64 compressed_size; /* out */
+ __u64 reserved[2];
+};
+
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -276,5 +286,7 @@ struct btrfs_ioctl_logical_ino_args {
struct btrfs_ioctl_ino_path_args)
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struct btrfs_ioctl_ino_path_args)
+#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \
+ struct btrfs_ioctl_compr_size_args)
#endif
--
1.7.7.3

View File

@ -0,0 +1,68 @@
From: Li Zefan <lizf@cn.fujitsu.com>
Date: Thu, 26 May 2011 11:39:03 +0800
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] Btrfs: make lzo the default compression scheme
As the lzo compression feature has been established for quite
a while, we are now ready to replace zlib with lzo as the default
compression scheme.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/disk-io.c | 2 +-
fs/btrfs/ioctl.c | 2 +-
fs/btrfs/super.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 94abc25..7ea0cdd 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2095,7 +2095,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
* In the long term, we'll store the compression type in the super
* block, and it'll be used for per file compression control.
*/
- fs_info->compress_type = BTRFS_COMPRESS_ZLIB;
+ fs_info->compress_type = BTRFS_COMPRESS_LZO;
ret = btrfs_parse_options(tree_root, options);
if (ret) {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index a90e749..d9c2ba6 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -992,7 +992,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
unsigned long ra_index = 0;
int ret;
int defrag_count = 0;
- int compress_type = BTRFS_COMPRESS_ZLIB;
+ int compress_type = BTRFS_COMPRESS_LZO;
int extent_thresh = range->extent_thresh;
int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
int cluster = max_cluster;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 8bd9d6d..b6b5bd7 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -270,12 +270,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
case Opt_compress_type:
if (token == Opt_compress ||
token == Opt_compress_force ||
- strcmp(args[0].from, "zlib") == 0) {
- compress_type = "zlib";
- info->compress_type = BTRFS_COMPRESS_ZLIB;
- } else if (strcmp(args[0].from, "lzo") == 0) {
+ strcmp(args[0].from, "lzo") == 0) {
compress_type = "lzo";
info->compress_type = BTRFS_COMPRESS_LZO;
+ } else if (strcmp(args[0].from, "zlib") == 0) {
+ compress_type = "zlib";
+ info->compress_type = BTRFS_COMPRESS_ZLIB;
} else {
ret = -EINVAL;
goto out;
--
1.7.6

View File

@ -0,0 +1,32 @@
From: David Sterba <dsterba@suse.cz>
Date: Thu, 15 Dec 2011 02:10:55 +0100
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] btrfs: workaround for cleaner deadlock
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/disk-io.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3f9d555..12d785b 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1572,11 +1572,13 @@ static int cleaner_kthread(void *arg)
vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
+ down_read_trylock(&root->fs_info->sb->s_umount) &&
mutex_trylock(&root->fs_info->cleaner_mutex)) {
btrfs_run_delayed_iputs(root);
btrfs_clean_old_snapshots(root);
mutex_unlock(&root->fs_info->cleaner_mutex);
btrfs_run_defrag_inodes(root->fs_info);
+ up_read(&root->fs_info->sb->s_umount);
}
if (freezing(current)) {
--
1.7.7.3

View File

@ -0,0 +1,61 @@
From: Li Zefan <lizf@cn.fujitsu.com>
Date: Wed, 7 Dec 2011 13:12:59 +0800
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] Btrfs: update global block_rsv when creating a new block
group
A bug was triggered while using seed device:
# mkfs.btrfs /dev/loop1
# btrfstune -S 1 /dev/loop1
# mount -o /dev/loop1 /mnt
# btrfs dev add /dev/loop2 /mnt
btrfs: block rsv returned -28
------------[ cut here ]------------
WARNING: at fs/btrfs/extent-tree.c:5969 btrfs_alloc_free_block+0x166/0x396 [btrfs]()
...
Call Trace:
...
[<f7b7c31c>] btrfs_cow_block+0x101/0x147 [btrfs]
[<f7b7eaa6>] btrfs_search_slot+0x1b8/0x55f [btrfs]
[<f7b7f844>] btrfs_insert_empty_items+0x42/0x7f [btrfs]
[<f7b7f8c1>] btrfs_insert_item+0x40/0x7e [btrfs]
[<f7b8ac02>] btrfs_make_block_group+0x243/0x2aa [btrfs]
[<f7bb3f53>] __btrfs_alloc_chunk+0x672/0x70e [btrfs]
[<f7bb41ff>] init_first_rw_device+0x77/0x13c [btrfs]
[<f7bb5a62>] btrfs_init_new_device+0x664/0x9fd [btrfs]
[<f7bbb65a>] btrfs_ioctl+0x694/0xdbe [btrfs]
[<c04f55f7>] do_vfs_ioctl+0x496/0x4cc
[<c04f5660>] sys_ioctl+0x33/0x4f
[<c07b9edf>] sysenter_do_call+0x12/0x38
---[ end trace 906adac595facc7d ]---
Since seed device is readonly, there's no usable space in the filesystem.
Afterwards we add a sprout device to it, and the kernel creates a METADATA
block group and a SYSTEM block group where comes free space we can reserve,
but we still get revervation failure because the global block_rsv hasn't
been updated accordingly.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/extent-tree.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8861572..a80efb5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7476,6 +7476,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
&cache->space_info);
BUG_ON(ret);
+ update_global_block_rsv(root->fs_info);
spin_lock(&cache->space_info->lock);
cache->space_info->bytes_readonly += cache->bytes_super;
--
1.7.6.233.gd79bc

View File

@ -0,0 +1,84 @@
From: Li Zefan <lizf@cn.fujitsu.com>
Date: Wed, 7 Dec 2011 13:13:26 +0800
Patch-mainline: pending
References: FATE#306586
Subject: [PATCH] Btrfs: fix possible deadlock when opening a seed device
The correct lock order is uuid_mutex -> volume_mutex -> chunk_mutex,
but when we mount a filesystem which has backing seed devices, we have
this lock chain:
open_ctree()
lock(chunk_mutex);
read_chunk_tree();
read_one_dev();
open_seed_devices();
lock(uuid_mutex);
and then we hit a lockdep splat.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/disk-io.c | 2 --
fs/btrfs/volumes.c | 9 +++++++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index d0bc3c5..beb1d19 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2287,9 +2287,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
(unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node),
BTRFS_UUID_SIZE);
- mutex_lock(&fs_info->chunk_mutex);
ret = btrfs_read_chunk_tree(chunk_root);
- mutex_unlock(&fs_info->chunk_mutex);
if (ret) {
printk(KERN_WARNING "btrfs: failed to read chunk tree on %s\n",
sb->s_id);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index d136915..fc94228 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4264,7 +4264,7 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
struct btrfs_fs_devices *fs_devices;
int ret;
- mutex_lock(&uuid_mutex);
+ BUG_ON(!mutex_is_locked(&uuid_mutex));
fs_devices = root->fs_info->fs_devices->seed;
while (fs_devices) {
@@ -4302,7 +4302,6 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
fs_devices->seed = root->fs_info->fs_devices->seed;
root->fs_info->fs_devices->seed = fs_devices;
out:
- mutex_unlock(&uuid_mutex);
return ret;
}
@@ -4459,6 +4458,9 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
if (!path)
return -ENOMEM;
+ mutex_lock(&uuid_mutex);
+ lock_chunks(root);
+
/* first we search for all of the device items, and then we
* read in all of the chunk items. This way we can create chunk
* mappings that reference all of the devices that are afound
@@ -4509,6 +4511,9 @@ again:
}
ret = 0;
error:
+ unlock_chunks(root);
+ mutex_unlock(&uuid_mutex);
+
btrfs_free_path(path);
return ret;
}
--
1.7.6.233.gd79bc

View File

@ -0,0 +1,47 @@
From: David Sterba <dsterba@suse.cz>
Date: Mon, 1 Aug 2011 18:11:57 +0200
Subject: [PATCH] btrfs: allow cross-subvolume file clone
Reference: bnc#698540
Patch-mainline: pending
Lift the EXDEV condition and allow different root trees for files being
cloned, then pass source inode's root when searching for extents.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ioctl.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0b980af..58eb0ef 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2183,7 +2183,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
goto out_fput;
ret = -EXDEV;
- if (src->i_sb != inode->i_sb || BTRFS_I(src)->root != root)
+ if (src->i_sb != inode->i_sb)
goto out_fput;
ret = -ENOMEM;
@@ -2247,13 +2247,14 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
* note the key will change type as we walk through the
* tree.
*/
- ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
+ 0, 0);
if (ret < 0)
goto out;
nritems = btrfs_header_nritems(path->nodes[0]);
if (path->slots[0] >= nritems) {
- ret = btrfs_next_leaf(root, path);
+ ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
if (ret < 0)
goto out;
if (ret > 0)
--
1.7.6

68
3.2.34/series Normal file
View File

@ -0,0 +1,68 @@
bump/1021_linux-3.2.22.patch
bump/1022_linux-3.2.23.patch
bump/1023_linux-3.2.24.patch
bump/1024_linux-3.2.25.patch
bump/1025_linux-3.2.26.patch
bump/1026_linux-3.2.27.patch
bump/1027_linux-3.2.28.patch
bump/1028_linux-3.2.29.patch
bump/1029_linux-3.2.30.patch
bump/1030_linux-3.2.31.patch
bump/1031_linux-3.2.32.patch
bump/1032_linux-3.2.33.patch
bump/1033_linux-3.2.34.patch
0001-block-prepare-I-O-context-code-for-BFQ-v5-for-3.2.patch
0002-block-cgroups-kconfig-build-bits-for-BFQ-v5-3.2.patch
0003-block-introduce-the-BFQ-v5-I-O-sched-for-3.2.patch
0001-AppArmor-compatibility-patch-for-v5-network-controll.patch
0002-AppArmor-compatibility-patch-for-v5-interface.patch
0003-AppArmor-Allow-dfa-backward-compatibility-with-broke.patch
cloneconfig.patch
kbuild-compress-kernel-modules-on-installation.patch
ata-prefer-ata-drivers-over-ide-drivers-when-both-are-built.patch
colored-printk-3.2.33.patch
910-kobject_uevent.patch
911-kobject_add_broadcast_uevent.patch
linux-2.6-x86-tune-generic.patch
hz-432-kconfig-option.patch
hz-864-kconfig-option.patch
Add_CONFIG_VFAT_FS_DUALNAMES_option.patch
linux-2.6-defaults-fat-utf8.patch
aufs3-standalone-3.2.patch
accessfs-3.2-0.26.patch
wrapfs-v3.2.2-45-ga5296eb.patch
imqmq-3.2.patch
vserver-3.2.34-vs2.3.2.15.patch
uksm-0.1.2.1-for-v3.2.ge.31.patch
kernel-3.4.0-layer7-2.22.patch
net-netfilter-IFWLOG.patch
net-netfilter-IFWLOG-mdv.patch
net-netfilter-IFWLOG-2.6.35-buildfix.patch
net-netfilter-IFWLOG-2.6.37-buildfix.patch
net-netfilter-psd.patch
net-netfilter-psd-mdv.patch
net-netfilter-psd-2.6.35-buildfix.patch
netfilter-implement-rfc-1123-for-ftp-conntrack.patch
netfilter-ip_conntrack_slp.patch
kernel-3.2-lsxhl.patch
kernel-3.2-lsproduo.patch
kernel-3.2-lsql.patch
v3.2-ARM-kirkwood-Add-support-for-Buffalo-LS-VL.patch
v3.2-ARM-kirkwood-Add-support-for-Buffalo-LS-WVL.patch
lschlv2.patch
3rd-3rdparty-1.0-tree.patch
3rd-3rdparty-merge.patch
3rd-3rdparty-netatop-0.1.1.patch
3rd-3rdparty-button_hotplug-0.4.1.patch
3rd-3rdparty-gpio_button_hotplug-0.1.patch
3rd-3rdparty-gpio_event_drv-0.1.patch

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-kirkwood/Kconfig linux-3.2.33-go/arch/arm/mach-kirkwood/Kconfig
--- linux-3.2.33-go.orig/arch/arm/mach-kirkwood/Kconfig 2012-11-14 21:20:22.326388580 +0100
+++ linux-3.2.33-go/arch/arm/mach-kirkwood/Kconfig 2012-11-14 21:21:02.353908681 +0100
@@ -136,6 +136,12 @@
Say 'Y' here if you want your kernel to support the
Buffalo LS-XHL Series.
+config MACH_LSVL
+ bool "Buffalo LS-VL Series"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo LS-VL Series.
+
endmenu
endif
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-kirkwood/lsvl-setup.c linux-3.2.33-go/arch/arm/mach-kirkwood/lsvl-setup.c
--- linux-3.2.33-go.orig/arch/arm/mach-kirkwood/lsvl-setup.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.2.33-go/arch/arm/mach-kirkwood/lsvl-setup.c 2012-11-14 21:22:54.158568343 +0100
@@ -0,0 +1,340 @@
+/*
+ * arch/arm/mach-kirkwood/lsvl-setup.c
+ *
+ * Buffalo LS-VL Series Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on BOOT Device
+ ****************************************************************************/
+static struct mtd_partition lsvl_partitions[] = {
+ {
+ .name = "u-boot",
+ .size = 0x80000,
+ .offset = 0x00000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }
+};
+
+static struct flash_platform_data lsvl_spi_slave_data = {
+ .type = "m25p40-nonjedec",
+ .parts = lsvl_partitions,
+ .nr_parts = ARRAY_SIZE(lsvl_partitions),
+};
+
+static struct spi_board_info __initdata lsvl_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lsvl_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ }
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+static struct mv643xx_eth_platform_data lsvl_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lsvl_sata_data = {
+ .n_ports = 1,
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+#define LSVL_GPIO_LED_ALARM 36
+#define LSVL_GPIO_LED_FUNC_RED 37
+#define LSVL_GPIO_LED_INFO 38
+#define LSVL_GPIO_LED_FUNC_BLUE 39
+#define LSVL_GPIO_LED_PWR 40
+
+static struct gpio_led lsvl_led_pins[] = {
+ {
+ .name = "alarm:red",
+ .gpio = LSVL_GPIO_LED_ALARM,
+ },
+ {
+ .name = "func:red:bottom",
+ .gpio = LSVL_GPIO_LED_FUNC_RED,
+ },
+ {
+ .name = "info:amber",
+ .gpio = LSVL_GPIO_LED_INFO,
+ },
+ {
+ .name = "func:blue:bottom",
+ .gpio = LSVL_GPIO_LED_FUNC_BLUE,
+ },
+
+ {
+ .name = "power:blue",
+ .default_trigger = "default-on",
+ .gpio = LSVL_GPIO_LED_PWR,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data lsvl_led_data = {
+ .leds = lsvl_led_pins,
+ .num_leds = ARRAY_SIZE(lsvl_led_pins),
+};
+
+static struct platform_device lsvl_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lsvl_led_data,
+ }
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSVL_GPIO_HDD_POWER 8
+#define LSVL_GPIO_USB_POWER 12
+
+/*****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+/*#define LSVL_GPIO_KEY_FUNC 45
+#define LSVL_GPIO_KEY_POWER 46
+#define LSVL_GPIO_KEY_AUTOPOWER 47
+#define LSVL_SW_POWER 0x00
+#define LSVL_SW_AUTOPOWER 0x01
+#define LSVL_SW_FUNC 0x02
+
+static struct gpio_keys_button lsvl_buttons[] = {
+ {
+ .type = EV_SW,
+ .code = LSVL_SW_POWER,
+ .gpio = LSVL_GPIO_KEY_POWER,
+ .desc = "Power-on Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSVL_SW_AUTOPOWER,
+ .gpio = LSVL_GPIO_KEY_AUTOPOWER,
+ .desc = "Power-auto Switch",
+ .active_low = 1,
+ }, {
+ .type = EV_SW,
+ .code = LSVL_SW_FUNC,
+ .gpio = LSVL_GPIO_KEY_FUNC,
+ .desc = "Function Button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data lsvl_button_data = {
+ .buttons = lsvl_buttons,
+ .nbuttons = ARRAY_SIZE(lsvl_buttons),
+};
+
+static struct platform_device lsvl_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsvl_button_data,
+ },
+};
+*/
+
+/*****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+#define LSVL_GPIO_FAN_HIGH 16
+#define LSVL_GPIO_FAN_LOW 17
+#define LSVL_GPIO_FAN_LOCK 43
+
+static struct gpio_fan_alarm lsvl_alarm = {
+ .gpio = LSVL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lsvl_speeds[] = {
+ {
+ .rpm = 0,
+ .ctrl_val = 3,
+ }, {
+ .rpm = 1500,
+ .ctrl_val = 1,
+ }, {
+ .rpm = 3250,
+ .ctrl_val = 2,
+ }, {
+ .rpm = 5000,
+ .ctrl_val = 0,
+ }
+};
+
+static int lsvl_gpio_list[] = {
+ LSVL_GPIO_FAN_HIGH, LSVL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lsvl_fan_data = {
+ .num_ctrl = ARRAY_SIZE(lsvl_gpio_list),
+ .ctrl = lsvl_gpio_list,
+ .alarm = &lsvl_alarm,
+ .num_speed = ARRAY_SIZE(lsvl_speeds),
+ .speed = lsvl_speeds,
+};
+
+static struct platform_device lsvl_fan_device = {
+ .name = "gpio-fan",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lsvl_fan_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static unsigned int lsvl_mpp_config[] __initdata = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP6_SYSRST_OUTn,
+ MPP7_SPI_SCn,
+ MPP8_GPIO, /* HDD Power */
+ MPP9_GPIO,
+ MPP10_UART0_TXD,
+ MPP11_UART0_RXD,
+ MPP12_GPO, /* USB VBUS EN */
+ MPP13_GPIO,
+ MPP14_GPIO,
+ MPP15_GPIO,
+ MPP16_GPIO, /* FAN HIGH: on:0, off:1 */
+ MPP17_GPIO, /* FAN LOW: on:0, off:1 */
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP20_GPIO,
+ MPP21_GPIO,
+ MPP22_GPIO,
+ MPP23_GPIO,
+ MPP24_GPIO,
+ MPP25_GPIO,
+ MPP26_GPIO,
+ MPP27_GPIO,
+ MPP28_GPIO,
+ MPP29_GPIO,
+ MPP30_GPIO,
+ MPP31_GPIO,
+ MPP32_GPIO,
+ MPP33_GPO,
+ MPP34_GPIO,
+ MPP35_GPIO,
+ MPP36_GPIO, /* ALARM LED */
+ MPP37_GPIO, /* FUNC RED LED */
+ MPP38_GPIO, /* INFO LED */
+ MPP39_GPIO, /* FUNC LED */
+ MPP40_GPIO, /* POWER LED */
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO, /* FAN LOCK */
+ MPP44_GPIO,
+ MPP45_GPIO, /* FUNC SW */
+ MPP46_GPIO, /* POWER SW */
+ MPP47_GPIO, /* POWER AUTO SW */
+ MPP48_GPIO, /* UART EN */
+ MPP49_GPIO,
+ 0
+};
+
+/*****************************************************************************
+ * LS-VL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-VL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ *
+ */
+
+static void lsvl_power_off(void)
+{
+ arm_machine_restart('h', NULL);
+}
+
+static void __init lsvl_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(lsvl_mpp_config);
+
+ /*
+ * Configure peripherals.
+ */
+ kirkwood_uart0_init();
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&lsvl_ge00_data);
+ kirkwood_sata_init(&lsvl_sata_data);
+ kirkwood_spi_init();
+
+ platform_device_register(&lsvl_leds);
+// platform_device_register(&lsvl_button_device);
+ platform_device_register(&lsvl_fan_device);
+
+ spi_register_board_info(lsvl_spi_slave_info,
+ ARRAY_SIZE(lsvl_spi_slave_info));
+
+ /* usb power on */
+ gpio_set_value(LSVL_GPIO_USB_POWER, 1);
+
+ /* register power-off method */
+ pm_power_off = lsvl_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LSVL, "Buffalo LS-VL Series")
+ .atag_offset = 0x100,
+ .init_machine = lsvl_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
+
diff -uNr linux-3.2.33-go.orig/arch/arm/mach-kirkwood/Makefile linux-3.2.33-go/arch/arm/mach-kirkwood/Makefile
--- linux-3.2.33-go.orig/arch/arm/mach-kirkwood/Makefile 2012-11-14 21:20:22.326388580 +0100
+++ linux-3.2.33-go/arch/arm/mach-kirkwood/Makefile 2012-11-14 21:22:20.882968794 +0100
@@ -19,5 +19,6 @@
obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
obj-$(CONFIG_MACH_T5325) += t5325-setup.o
obj-$(CONFIG_MACH_LSXHL) += lsxhl-setup.o
+obj-$(CONFIG_MACH_LSVL) += lsvl-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff -uNr linux-3.2.33-go.orig/arch/arm/tools/mach-types linux-3.2.33-go/arch/arm/tools/mach-types
--- linux-3.2.33-go.orig/arch/arm/tools/mach-types 2012-11-14 21:20:22.348388327 +0100
+++ linux-3.2.33-go/arch/arm/tools/mach-types 2012-11-14 21:21:02.356908648 +0100
@@ -118,6 +118,7 @@
omap_osk MACH_OMAP_OSK OMAP_OSK 515
tosa MACH_TOSA TOSA 520
avila MACH_AVILA AVILA 526
+lsvl MACH_LSVL LSVL 5277
edb9302 MACH_EDB9302 EDB9302 538
husky MACH_HUSKY HUSKY 543
shepherd MACH_SHEPHERD SHEPHERD 545

View File

@ -0,0 +1,538 @@
diff -uNr linux-3.2.34-go.orig/arch/arm/mach-kirkwood/Kconfig linux-3.2.34-go/arch/arm/mach-kirkwood/Kconfig
--- linux-3.2.34-go.orig/arch/arm/mach-kirkwood/Kconfig 2012-11-19 21:03:42.654743005 +0100
+++ linux-3.2.34-go/arch/arm/mach-kirkwood/Kconfig 2012-11-19 21:04:02.744505974 +0100
@@ -148,6 +148,12 @@
Say 'Y' here if you want your kernel to support the
Buffalo LS-CHLv2 Series.
+config MACH_LSWVL
+ bool "Buffalo LS-WVL Series"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Buffalo LS-WVL/E-AP NAS
+
endmenu
endif
diff -uNr linux-3.2.34-go.orig/arch/arm/mach-kirkwood/lswvl-setup.c linux-3.2.34-go/arch/arm/mach-kirkwood/lswvl-setup.c
--- linux-3.2.34-go.orig/arch/arm/mach-kirkwood/lswvl-setup.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-3.2.34-go/arch/arm/mach-kirkwood/lswvl-setup.c 2012-11-19 21:04:02.745505962 +0100
@@ -0,0 +1,366 @@
+/*
+ * arch/arm/mach-kirkwood/lswvl-setup.c
+ *
+ * Buffalo LS-WVL Series Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/orion_nand.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+
+/*****************************************************************************
+ * 512MB NAND Flash on Device bus CS0
+ ****************************************************************************/
+static struct mtd_partition lswvl_nand_parts[] = {
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = 16 * 1024 * 1024,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 488 * 1024 * 1024,
+ }, {
+ .name = "reserve",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+/*****************************************************************************
+ * 512KB NOR Flash on BOOT Device
+ ****************************************************************************/
+static struct mtd_partition lswvl_partitions[] = {
+ {
+ .name = "u-boot",
+ .size = 0x80000,
+ .offset = 0x00000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+};
+
+static struct flash_platform_data lswvl_spi_slave_data = {
+ .parts = lswvl_partitions,
+ .nr_parts = ARRAY_SIZE(lswvl_partitions),
+};
+
+static struct spi_board_info __initdata lswvl_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lswvl_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ },
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+static struct mv643xx_eth_platform_data lswvl_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lswvl_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+#define LSWVL_GPIO_LED_HDDERR0 34
+#define LSWVL_GPIO_LED_HDDERR1 35
+#define LSWVL_GPIO_LED_ALARM 36
+#define LSWVL_GPIO_LED_FUNC_RED 37
+#define LSWVL_GPIO_LED_INFO 38
+#define LSWVL_GPIO_LED_FUNC_BLUE 39
+#define LSWVL_GPIO_LED_PWR 40
+
+static struct gpio_led lswvl_led_pins[] = {
+ {
+ .name = "lswvl:hdderr:0",
+ .gpio = LSWVL_GPIO_LED_HDDERR0,
+ }, {
+ .name = "lswvl:hdderr:1",
+ .gpio = LSWVL_GPIO_LED_HDDERR1,
+ }, {
+ .name = "lswvl:alarm:red",
+ .gpio = LSWVL_GPIO_LED_ALARM,
+ }, {
+ .name = "lswvl:func:red",
+ .gpio = LSWVL_GPIO_LED_FUNC_RED,
+ }, {
+ .name = "lswvl:info:amber",
+ .gpio = LSWVL_GPIO_LED_INFO,
+ }, {
+ .name = "lswvl:func:blue",
+ .gpio = LSWVL_GPIO_LED_FUNC_BLUE,
+ }, {
+ .name = "lswvl:power:blue",
+ .default_trigger = "default-on",
+ .gpio = LSWVL_GPIO_LED_PWR,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data lswvl_led_data = {
+ .leds = lswvl_led_pins,
+ .num_leds = ARRAY_SIZE(lswvl_led_pins),
+};
+
+static struct platform_device lswvl_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &lswvl_led_data,
+ }
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSWVL_GPIO_HDD0_POWER 8
+#define LSWVL_GPIO_HDD1_POWER 9
+#define LSWVL_GPIO_USB_POWER 12
+
+/*****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LSWVL_GPIO_KEY_FUNC 45
+#define LSWVL_GPIO_KEY_POWER 46
+#define LSWVL_GPIO_KEY_AUTOPOWER 47
+#define LSWVL_SW_POWER 0x00
+#define LSWVL_SW_AUTOPOWER 0x01
+#define LSWVL_SW_FUNC 0x02
+
+static struct gpio_keys_button lswvl_buttons[] = {
+ {
+ .type = EV_KEY,
+ .code = BTN_1,
+ .gpio = LSWVL_GPIO_KEY_POWER,
+ .desc = "power-on",
+ .active_low = 1,
+ }, {
+ .type = EV_KEY,
+ .code = BTN_2,
+ .gpio = LSWVL_GPIO_KEY_AUTOPOWER,
+ .desc = "power-auto",
+ .active_low = 1,
+ }, {
+ .type = EV_KEY,
+ .code = BTN_0,
+ .gpio = LSWVL_GPIO_KEY_FUNC,
+ .desc = "function",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data lswvl_button_data = {
+ .buttons = lswvl_buttons,
+ .nbuttons = ARRAY_SIZE(lswvl_buttons),
+};
+
+static struct platform_device lswvl_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lswvl_button_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+#define LSWVL_GPIO_FAN_HIGH 16
+#define LSWVL_GPIO_FAN_LOW 17
+#define LSWVL_GPIO_FAN_LOCK 43
+
+static struct gpio_fan_alarm lswvl_alarm = {
+ .gpio = LSWVL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lswvl_speeds[] = {
+ {
+ .rpm = 0,
+ .ctrl_val = 3,
+ }, {
+ .rpm = 1500,
+ .ctrl_val = 1,
+ }, {
+ .rpm = 3250,
+ .ctrl_val = 2,
+ }, {
+ .rpm = 5000,
+ .ctrl_val = 0,
+ }
+};
+
+static int lswvl_gpio_list[] = {
+ LSWVL_GPIO_FAN_HIGH, LSWVL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lswvl_fan_data = {
+ .num_ctrl = ARRAY_SIZE(lswvl_gpio_list),
+ .ctrl = lswvl_gpio_list,
+ .alarm = &lswvl_alarm,
+ .num_speed = ARRAY_SIZE(lswvl_speeds),
+ .speed = lswvl_speeds,
+};
+
+static struct platform_device lswvl_fan_device = {
+ .name = "gpio-fan",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &lswvl_fan_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static unsigned int lswvl_mpp_config[] __initdata = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP6_SYSRST_OUTn,
+ MPP7_SPI_SCn,
+ MPP8_GPIO, /* HDD Power */
+ MPP9_GPIO, /* HDD Power */
+ MPP10_UART0_TXD,
+ MPP11_UART0_RXD,
+ MPP12_GPO, /* USB VBUS EN */
+ MPP13_GPIO,
+ MPP14_GPIO,
+ MPP15_GPIO,
+ MPP16_GPIO, /* FAN HIGH: on:0, off:1 */
+ MPP17_GPIO, /* FAN LOW: on:0, off:1 */
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP20_GPIO,
+ MPP21_GPIO,
+ MPP22_GPIO,
+ MPP23_GPIO,
+ MPP24_GPIO,
+ MPP25_GPIO,
+ MPP26_GPIO,
+ MPP27_GPIO,
+ MPP28_GPIO,
+ MPP29_GPIO,
+ MPP30_GPIO,
+ MPP31_GPIO,
+ MPP32_GPIO,
+ MPP33_GPO,
+ MPP34_GPIO, /*HDD ERROR LED 0*/
+ MPP35_GPIO, /*HDD ERROR LED 1*/
+ MPP36_GPIO, /* ALARM LED */
+ MPP37_GPIO, /* FUNC RED LED */
+ MPP38_GPIO, /* INFO LED */
+ MPP39_GPIO, /* FUNC LED */
+ MPP40_GPIO, /* POWER LED */
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO, /* FAN LOCK */
+ MPP44_GPIO,
+ MPP45_GPIO, /* FUNC SW */
+ MPP46_GPIO, /* POWER SW */
+ MPP47_GPIO, /* POWER AUTO SW */
+ MPP48_GPIO, /* UART EN */
+ MPP49_GPIO,
+ 0
+};
+
+/*****************************************************************************
+ * LS-WVL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-WVL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ * to move the switch to ON position
+ *
+ */
+
+static void lswvl_power_off(void)
+{
+ arm_machine_restart('h', NULL); //kirkwood_restart('h', NULL);
+}
+
+static void __init lswvl_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(lswvl_mpp_config);
+
+ /*
+ * Configure peripherals.
+ */
+ kirkwood_ge00_init(&lswvl_ge00_data);
+ kirkwood_uart0_init();
+ kirkwood_uart1_init();
+ kirkwood_ehci_init();
+ kirkwood_sata_init(&lswvl_sata_data);
+
+ spi_register_board_info(lswvl_spi_slave_info,
+ ARRAY_SIZE(lswvl_spi_slave_info));
+ kirkwood_spi_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(lswvl_nand_parts), 25);
+
+ platform_device_register(&lswvl_leds);
+ platform_device_register(&lswvl_button_device);
+ platform_device_register(&lswvl_fan_device);
+
+ /* usb power on */
+ gpio_set_value(LSWVL_GPIO_USB_POWER, 1);
+
+ /* register power-off method */
+ pm_power_off = lswvl_power_off;
+
+ pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LSWVL, "Buffalo LS-WVL Series")
+ .atag_offset = 0x100,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+ .init_machine = lswvl_init,
+ // .restart = kirkwood_restart,
+MACHINE_END
+
diff -uNr linux-3.2.34-go.orig/arch/arm/mach-kirkwood/Makefile linux-3.2.34-go/arch/arm/mach-kirkwood/Makefile
--- linux-3.2.34-go.orig/arch/arm/mach-kirkwood/Makefile 2012-11-19 21:03:42.653743017 +0100
+++ linux-3.2.34-go/arch/arm/mach-kirkwood/Makefile 2012-11-19 21:04:42.686036907 +0100
@@ -21,5 +21,6 @@
obj-$(CONFIG_MACH_LINKSTATION_CHLV2) += lschlv2-setup.o
obj-$(CONFIG_MACH_LSXHL) += lsxhl-setup.o
obj-$(CONFIG_MACH_LSVL) += lsvl-setup.o
+obj-$(CONFIG_MACH_LSWVL) += lswvl-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff -uNr linux-3.2.34-go.orig/arch/arm/plat-orion/mpp.c linux-3.2.34-go/arch/arm/plat-orion/mpp.c
--- linux-3.2.34-go.orig/arch/arm/plat-orion/mpp.c 2012-11-19 21:03:42.766741717 +0100
+++ linux-3.2.34-go/arch/arm/plat-orion/mpp.c 2012-11-19 21:04:02.747505938 +0100
@@ -15,6 +15,7 @@
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <plat/mpp.h>
+#include <asm/mach-types.h>
/* Address of the ith MPP control register */
static __init unsigned long mpp_ctrl_addr(unsigned int i,
@@ -75,3 +76,37 @@
}
printk("\n");
}
+
+#ifdef CONFIG_MACH_LSWVL
+
+static u32 boot_mpp_value = 0x21111111;
+/*
+ * change MPP[3:1] to SPI mode
+ */
+void lswvl_setup_spi_mpp(void)
+{
+ u32 spival = 0;
+ u32 bootval = 0;
+
+ spival = 0x00002220;
+ boot_mpp_value = bootval = readl(mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+ bootval &= 0xffff000f;
+ writel(spival | bootval, mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+}
+
+/*
+ * change back MPP[3:1] to default configuration
+ */
+void lswvl_reset_mpp(void)
+{
+ u32 spival = 0;
+ u32 bootval = 0;
+
+ spival = readl(mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+ spival &= 0xffff000f;
+ bootval = boot_mpp_value & ~0xffff000f;
+ writel(spival | bootval, mpp_ctrl_addr(0, DEV_BUS_VIRT_BASE));
+}
+
+#endif
+
diff -uNr linux-3.2.34-go.orig/arch/arm/tools/mach-types linux-3.2.34-go/arch/arm/tools/mach-types
--- linux-3.2.34-go.orig/arch/arm/tools/mach-types 2012-11-19 21:03:42.675742765 +0100
+++ linux-3.2.34-go/arch/arm/tools/mach-types 2012-11-19 21:22:29.653445807 +0100
@@ -119,6 +119,7 @@
tosa MACH_TOSA TOSA 520
avila MACH_AVILA AVILA 526
lsvl MACH_LSVL LSVL 5277
+lswvl MACH_LSWVL LSWVL 5278
edb9302 MACH_EDB9302 EDB9302 538
husky MACH_HUSKY HUSKY 543
shepherd MACH_SHEPHERD SHEPHERD 545
diff -uNr linux-3.2.34-go.orig/drivers/spi/spi-orion.c linux-3.2.34-go/drivers/spi/spi-orion.c
--- linux-3.2.34-go.orig/drivers/spi/spi-orion.c 2012-11-19 21:03:41.809752734 +0100
+++ linux-3.2.34-go/drivers/spi/spi-orion.c 2012-11-19 21:20:55.123558883 +0100
@@ -19,6 +19,12 @@
#include <linux/spi/orion_spi.h>
#include <linux/module.h>
#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+
+#ifdef CONFIG_MACH_LSWVL
+void lswvl_setup_spi_mpp(void);
+void lswvl_reset_mpp(void);
+#endif
#define DRIVER_NAME "orion_spi"
@@ -141,6 +147,9 @@
unsigned int bits_per_word = spi->bits_per_word;
int rc;
+#ifdef CONFIG_MACH_LSWVL
+ lswvl_setup_spi_mpp();
+#endif
orion_spi = spi_master_get_devdata(spi->master);
if ((t != NULL) && t->speed_hz)
@@ -153,15 +162,37 @@
if (rc)
return rc;
+#ifdef CONFIG_MACH_LSWVL
+ rc = orion_spi_set_transfer_size(orion_spi, bits_per_word);
+ lswvl_reset_mpp();
+ return rc;
+#else
return orion_spi_set_transfer_size(orion_spi, bits_per_word);
+#endif
}
static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
{
if (enable)
+#ifdef CONFIG_MACH_LSWVL
+ {
+ lswvl_setup_spi_mpp();
+ udelay(1);
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+ }
+#else
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+#endif
else
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+#ifdef CONFIG_MACH_LSWVL
+ {
+ orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+ lswvl_reset_mpp();
+ }
+#else
+ orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+#endif
}
static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
@@ -361,8 +392,17 @@
/* Fix ac timing if required. */
if (orion_spi->spi_info->enable_clock_fix)
+#ifdef CONFIG_MACH_LSWVL
+ {
+ lswvl_setup_spi_mpp();
+ orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+ (1 << 14));
+ lswvl_reset_mpp();
+ }
+#else
orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
(1 << 14));
+#endif
if ((spi->max_speed_hz == 0)
|| (spi->max_speed_hz > orion_spi->max_speed))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,553 @@
From dc13dec93dbd04bfa7a9ba67df1b8ed3431d8d48 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:39 -0700
Subject: [PATCH 1/3] AppArmor: compatibility patch for v5 network controll
Add compatibility for v5 network rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
include/linux/lsm_audit.h | 4 +
security/apparmor/Makefile | 19 ++++-
security/apparmor/include/net.h | 40 +++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 48 ++++++++++-
8 files changed, 394 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 88e78de..c63979a 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -124,6 +124,10 @@ struct common_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
} apparmor_audit_data;
#endif
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50..7cefef9 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o
+ resource.o sid.o file.o net.o
-clean-files := capability_names.h rlim_names.h
+clean-files := capability_names.h rlim_names.h af_names.h
# Build a lower case string table of capability names
@@ -44,9 +44,24 @@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
echo "};" >> $@
+# Build a lower case string table of address family names.
+# Transform lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [2] = "inet",
+quiet_cmd_make-af = GEN $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
+ sed $< >> $@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+).*/[\2] = "\L\1",/p';\
+ echo "};" >> $@
+
+
$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
+$(obj)/net.o : $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
$(call cmd,make-rlim)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
\ No newline at end of file
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..3c7d599
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+ u16 allow[AF_MAX];
+ u16 audit[AF_MAX];
+ u16 quiet[AF_MAX];
+};
+
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
+ int type, int protocol, struct sock *sk);
+extern int aa_revalidate_sk(int op, struct sock *sk);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+ /* NOP */
+}
+
+#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index aeda5cf..6776929 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -27,6 +27,7 @@
#include "capability.h"
#include "domain.h"
#include "file.h"
+#include "net.h"
#include "resource.h"
extern const char *profile_mode_names[];
@@ -145,6 +146,7 @@ struct aa_namespace {
* @size: the memory consumed by this profiles rules
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
+ * @net: network controls for the profile
* @rlimits: rlimits for the profile
*
* The AppArmor profile contains the basic confinement data. Each profile
@@ -181,6 +183,7 @@ struct aa_profile {
struct aa_file_rules file;
struct aa_caps caps;
+ struct aa_net net;
struct aa_rlimit rlimits;
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 3d2fd14..aa293ae 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -32,6 +32,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
+#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
@@ -621,6 +622,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
return error;
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
+ NULL);
+ return error;
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_BIND, sk);
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_CONNECT, sk);
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_LISTEN, sk);
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_ACCEPT, sk);
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SENDMSG, sk);
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_RECVMSG, sk);
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -652,6 +751,19 @@ static struct security_operations apparmor_ops = {
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .socket_create = apparmor_socket_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
+
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 0000000..1765901
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,170 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "af_names.h"
+
+static const char *sock_type_names[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ audit_log_format(ab, " family=");
+ if (address_family_names[sa->u.net.family]) {
+ audit_log_string(ab, address_family_names[sa->u.net.family]);
+ } else {
+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
+ }
+
+ audit_log_format(ab, " sock_type=");
+ if (sock_type_names[sa->aad.net.type]) {
+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
+ }
+
+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
+}
+
+/**
+ * audit_net - audit network access
+ * @profile: profile being enforced (NOT NULL)
+ * @op: operation being checked
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ * @sk: socket auditing is being applied to
+ * @error: error code for failure else 0
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+ int protocol, struct sock *sk, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa;
+ if (sk) {
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
+ } else {
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ }
+ /* todo fill in socket addr info */
+
+ sa.aad.op = op,
+ sa.u.net.family = family;
+ sa.u.net.sk = sk;
+ sa.aad.net.type = type;
+ sa.aad.net.protocol = protocol;
+ sa.aad.error = error;
+
+ if (likely(!sa.aad.error)) {
+ u16 audit_mask = profile->net.audit[sa.u.net.family];
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+ !(1 << sa.aad.net.type & audit_mask)))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
+ u16 kill_mask = 0;
+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
+
+ if (denied & kill_mask)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ if ((denied & quiet_mask) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+ }
+
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @op: operation being checked
+ * @profile: profile being enforced (NOT NULL)
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
+ int protocol, struct sock *sk)
+{
+ u16 family_mask;
+ int error;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->net.allow[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ return audit_net(profile, op, family, type, protocol, sk, error);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @op: operation being checked
+ * @sk: sock being revalidated (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(int op, struct sock *sk)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* aa_revalidate_sk should not be called from interrupt context
+ * don't mediate these calls as they are not task related
+ */
+ if (in_interrupt())
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
+ sk->sk_protocol, sk);
+
+ return error;
+}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 4f0eade..4d5ce13 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
aa_free_file_rules(&profile->file);
aa_free_cap_rules(&profile->caps);
+ aa_free_net_rules(&profile->net);
aa_free_rlimit_rules(&profile->rlimits);
aa_free_sid(profile->sid);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index d6d9a57..f4874c4 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -190,6 +190,19 @@ fail:
return 0;
}
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+ if (unpack_nameX(e, AA_U16, name)) {
+ if (!inbounds(e, sizeof(u16)))
+ return 0;
+ if (data)
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+ e->pos += sizeof(u16);
+ return 1;
+ }
+ return 0;
+}
+
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
if (unpack_nameX(e, AA_U32, name)) {
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
if (!unpack_rlimits(e, profile))
goto fail;
+ size = unpack_array(e, "net_allowed_af");
+ if (size) {
+
+ for (i = 0; i < size; i++) {
+ /* discard extraneous rules that this kernel will
+ * never request
+ */
+ if (i >= AF_MAX) {
+ u16 tmp;
+ if (!unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL))
+ goto fail;
+ continue;
+ }
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ /*
+ * allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ }
+ profile->net.allow[AF_UNIX] = 0xffff;
+ profile->net.allow[AF_NETLINK] = 0xffff;
+
/* get file rules */
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {
--
1.7.5.4

View File

@ -0,0 +1,99 @@
From 2ddeb856c43f60139fc5c8e2ed9bc350b9bed590 Mon Sep 17 00:00:00 2001
From: Arianna Avanzini <avanzini.arianna@gmail.com>
Date: Sat, 4 Feb 2012 10:55:51 +0100
Subject: [PATCH 1/2] block: cgroups, kconfig, build bits for BFQ-v5-3.3
Update Kconfig.iosched to include kernel configuration options
for BFQ. Add a Kconfig option and do the related Makefile changes
to compile the scheduler. Also let the cgroups subsystem know about
the BFQ I/O controller.
Signed-off-by: Fabio Checconi <fabio@gandalf.sssup.it>
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
---
block/Kconfig.iosched | 26 ++++++++++++++++++++++++++
block/Makefile | 1 +
include/linux/cgroup_subsys.h | 6 ++++++
3 files changed, 33 insertions(+)
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 3199b76..5905452 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -43,6 +43,28 @@ config CFQ_GROUP_IOSCHED
---help---
Enable group IO scheduling in CFQ.
+config IOSCHED_BFQ
+ tristate "BFQ I/O scheduler"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ The BFQ I/O scheduler tries to distribute bandwidth among
+ all processes according to their weights.
+ It aims at distributing the bandwidth as desired, independently of
+ the disk parameters and with any workload. It also tries to
+ guarantee low latency to interactive and soft real-time
+ applications. If compiled built-in (saying Y here), BFQ can
+ be configured to support hierarchical scheduling.
+
+config CGROUP_BFQIO
+ bool "BFQ hierarchical scheduling support"
+ depends on CGROUPS && IOSCHED_BFQ=y
+ default n
+ ---help---
+ Enable hierarchical scheduling in BFQ, using the cgroups
+ filesystem interface. The name of the subsystem will be
+ bfqio.
+
choice
prompt "Default I/O scheduler"
default DEFAULT_CFQ
@@ -56,6 +78,9 @@ choice
config DEFAULT_CFQ
bool "CFQ" if IOSCHED_CFQ=y
+ config DEFAULT_BFQ
+ bool "BFQ" if IOSCHED_BFQ=y
+
config DEFAULT_NOOP
bool "No-op"
@@ -65,6 +90,7 @@ config DEFAULT_IOSCHED
string
default "deadline" if DEFAULT_DEADLINE
default "cfq" if DEFAULT_CFQ
+ default "bfq" if DEFAULT_BFQ
default "noop" if DEFAULT_NOOP
endmenu
diff --git a/block/Makefile b/block/Makefile
index 39b76ba..c0d20fa 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 0bd390c..cbf22b1 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -72,3 +72,9 @@ SUBSYS(net_prio)
#endif
/* */
+
+#ifdef CONFIG_CGROUP_BFQIO
+SUBSYS(bfqio)
+#endif
+
+/* */
--
1.7.10.4

View File

@ -0,0 +1,391 @@
From a2515f25ad5a7833ddc5a032d34eee6a5ddee3a2 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:40 -0700
Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 1 +
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 18 ++-
security/apparmor/include/apparmorfs.h | 6 +
5 files changed, 319 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/apparmorfs-24.c
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b..51ebf96 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
boot.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+ bool "Enable AppArmor 2.4 compatability"
+ depends on SECURITY_APPARMOR
+ default y
+ help
+ This option enables compatability with AppArmor 2.4. It is
+ recommended if compatability with older versions of AppArmor
+ is desired.
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 7cefef9..0bb604b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o sid.o file.o net.o
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
clean-files := capability_names.h rlim_names.h af_names.h
diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
new file mode 100644
index 0000000..dc8c744
--- /dev/null
+++ b/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,287 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+ "user::other";
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+ .read = aa_features_read,
+};
+
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ struct aa_namespace *parent;
+
+ /* is next namespace a child */
+ if (!list_empty(&ns->sub_ns)) {
+ struct aa_namespace *next;
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+ read_lock(&next->lock);
+ return next;
+ }
+
+ /* check if the next ns is a sibling, parent, gp, .. */
+ parent = ns->parent;
+ while (parent) {
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+ read_lock(&ns->lock);
+ return ns;
+ }
+ if (parent == root)
+ return NULL;
+ ns = parent;
+ parent = parent->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+static struct aa_profile *__first_profile(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ for ( ; ns; ns = __next_namespace(root, ns)) {
+ if (!list_empty(&ns->base.profiles))
+ return list_first_entry(&ns->base.profiles,
+ struct aa_profile, base.list);
+ }
+ return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+ struct aa_profile *parent;
+ struct aa_namespace *ns = p->ns;
+
+ /* is next profile a child */
+ if (!list_empty(&p->base.profiles))
+ return list_first_entry(&p->base.profiles, typeof(*p),
+ base.list);
+
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
+ parent = p->parent;
+ while (parent) {
+ list_for_each_entry_continue(p, &parent->base.profiles,
+ base.list)
+ return p;
+ p = parent;
+ parent = parent->parent;
+ }
+
+ /* is next another profile in the namespace */
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace (NOT NULL)
+ * @profile: current profile (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+ struct aa_profile *profile)
+{
+ struct aa_profile *next = __next_profile(profile);
+ if (next)
+ return next;
+
+ /* finished all profiles in namespace move to next namespace */
+ return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+ __acquires(root->lock)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *root = aa_current_profile()->ns;
+ loff_t l = *pos;
+ f->private = aa_get_namespace(root);
+
+
+ /* find the first profile */
+ read_lock(&root->lock);
+ profile = __first_profile(root, root);
+
+ /* skip to position */
+ for (; profile && l > 0; l--)
+ profile = next_profile(root, profile);
+
+ return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private;
+ (*pos)++;
+
+ return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+ __releases(root->lock)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private, *ns;
+
+ if (profile) {
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+ read_unlock(&ns->lock);
+ }
+ read_unlock(&root->lock);
+ aa_put_namespace(root);
+}
+
+/**
+ * seq_show_profile - show a profile entry
+ * @f: seq_file to file
+ * @p: current position (profile) (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_namespace *root = f->private;
+
+ if (profile->ns != root)
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+ return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
+
+static int profiles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int profiles_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+const struct file_operations aa_fs_profiles_fops = {
+ .open = profiles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = profiles_release,
+};
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 0848292..28c52ac 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
aafs_remove(".remove");
aafs_remove(".replace");
aafs_remove(".load");
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ aafs_remove("profiles");
+ aafs_remove("matching");
+ aafs_remove("features");
+#endif
securityfs_remove(aa_fs_dentry);
aa_fs_dentry = NULL;
}
@@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
aa_fs_dentry = NULL;
goto error;
}
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+ if (error)
+ goto error;
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
+ if (error)
+ goto error;
+#endif
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a..14f955c 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,4 +17,10 @@
extern void __init aa_destroy_aafs(void);
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+extern const struct file_operations aa_fs_profiles_fops;
+#endif
+
#endif /* __AA_APPARMORFS_H */
--
1.7.5.4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
From 7a10d093f9779f42cb8d6affcb6a4436d3ebd6d3 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:41 -0700
Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken
userspace
The apparmor_parser when compiling policy could generate invalid dfas
that did not have sufficient padding to avoid invalid references, when
used by the kernel. The kernels check to verify the next/check table
size was broken meaning invalid dfas were being created by userspace
and not caught.
To remain compatible with old tools that are not fixed, pad the loaded
dfas next/check table. The dfa's themselves are valid except for the
high padding for potentially invalid transitions (high bounds error),
which have a maximimum is 256 entries. So just allocate an extra null filled
256 entries for the next/check tables. This will guarentee all bounds
are good and invalid transitions go to the null (0) state.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/match.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4..081491e 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -57,8 +57,17 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
if (bsize < tsize)
goto out;
+ /* Pad table allocation for next/check by 256 entries to remain
+ * backwards compatible with old (buggy) tools and remain safe without
+ * run time checks
+ */
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
+ tsize += 256 * th.td_flags;
+
table = kvmalloc(tsize);
if (table) {
+ /* ensure the pad is clear, else there will be errors */
+ memset(table, 0, tsize);
*table = th;
if (th.td_flags == YYTD_DATA8)
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
goto out;
if (flags & DFA_FLAG_VERIFY_STATES) {
+ int warning = 0;
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
/* TODO: do check that DEF state recursion terminates */
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (warning)
+ continue;
+ printk(KERN_WARNING "AppArmor DFA next/check "
+ "upper bounds error fixed, upgrade "
+ "user space tools \n");
+ warning = 1;
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;
--
1.7.5.4

View File

@ -0,0 +1,174 @@
diff --git a/block/blk-core.c b/block/blk-core.c
index d1a9a0a..8b54acb 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -73,6 +73,17 @@ static void drive_stat_acct(struct request *rq, int new_io)
part_inc_in_flight(part, rw);
}
+ switch (rw) { /* ATOP */
+ case READ: /* ATOP */
+ current->group_leader->stat.dsk_rio += new_io; /* ATOP */
+ current->group_leader->stat.dsk_rsz += blk_rq_sectors(rq); /* ATOP */
+ break; /* ATOP */
+ case WRITE: /* ATOP */
+ current->group_leader->stat.dsk_wio += new_io; /* ATOP */
+ current->group_leader->stat.dsk_wsz += blk_rq_sectors(rq); /* ATOP */
+ break; /* ATOP */
+ } /* ATOP */
+
part_stat_unlock();
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 13b5d07..cac522e 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -515,6 +515,25 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
(unsigned long long)delayacct_blkio_ticks(task),
cputime_to_clock_t(gtime),
cputime_to_clock_t(cgtime));
+
+ seq_printf(m, /* ATOP */
+ "%lu %llu %lu %llu %lu %llu %lu " /* ATOP */
+ "%llu %lu %llu %lu %llu %lu %lu\n", /* ATOP */
+ task->stat.dsk_rio, /* ATOP */
+ task->stat.dsk_rsz, /* ATOP */
+ task->stat.dsk_wio, /* ATOP */
+ task->stat.dsk_wsz, /* ATOP */
+ task->stat.tcp_snd, /* ATOP */
+ task->stat.tcp_ssz, /* ATOP */
+ task->stat.tcp_rcv, /* ATOP */
+ task->stat.tcp_rsz, /* ATOP */
+ task->stat.udp_snd, /* ATOP */
+ task->stat.udp_ssz, /* ATOP */
+ task->stat.udp_rcv, /* ATOP */
+ task->stat.udp_rsz, /* ATOP */
+ task->stat.raw_snd, /* ATOP */
+ task->stat.raw_rcv); /* ATOP */
+
if (mm)
mmput(mm);
return 0;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 78efe7c..22391bf 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1512,6 +1512,17 @@ struct task_struct {
#endif
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
+
+ struct { /* ATOP */
+ unsigned long dsk_rio, dsk_wio; /* ATOP */
+ unsigned long long dsk_rsz, dsk_wsz; /* ATOP */
+ unsigned long tcp_snd, tcp_rcv; /* ATOP */
+ unsigned long long tcp_ssz, tcp_rsz; /* ATOP */
+ unsigned long udp_snd, udp_rcv; /* ATOP */
+ unsigned long long udp_ssz, udp_rsz; /* ATOP */
+ unsigned long raw_snd, raw_rcv; /* ATOP */
+ } stat; /* ATOP */
+
/*
* cache last used pipe for splice
diff --git a/kernel/acct.c b/kernel/acct.c
index a6605ca..d5df53a 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -565,7 +565,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,
ac.ac_exitcode = pacct->ac_exitcode;
spin_unlock_irq(&current->sighand->siglock);
ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
- ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
+ ac.ac_rw = encode_comp_t(current->stat.dsk_rio + current->stat.dsk_wio); /* ATOP */
ac.ac_swaps = encode_comp_t(0);
/*
diff --git a/kernel/fork.c b/kernel/fork.c
index f88bd98..bab2085 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -683,6 +683,14 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
tsk->min_flt = tsk->maj_flt = 0;
tsk->nvcsw = tsk->nivcsw = 0;
+ tsk->stat.dsk_rio = tsk->stat.dsk_wio = 0; /* ATOP */
+ tsk->stat.dsk_rsz = tsk->stat.dsk_wsz = 0; /* ATOP */
+ tsk->stat.tcp_snd = tsk->stat.tcp_rcv = 0; /* ATOP */
+ tsk->stat.tcp_ssz = tsk->stat.tcp_rsz = 0; /* ATOP */
+ tsk->stat.udp_snd = tsk->stat.udp_rcv = 0; /* ATOP */
+ tsk->stat.udp_ssz = tsk->stat.udp_rsz = 0; /* ATOP */
+ tsk->stat.raw_snd = tsk->stat.raw_rcv = 0; /* ATOP */
+
#ifdef CONFIG_DETECT_HUNG_TASK
tsk->last_switch_count = tsk->nvcsw + tsk->nivcsw;
#endif
diff --git a/net/socket.c b/net/socket.c
index 769c386..3ba19f6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -547,10 +547,28 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
si->size = size;
err = security_socket_sendmsg(sock, msg, size);
- if (err)
- return err;
-
- return sock->ops->sendmsg(iocb, sock, msg, size);
+ if (!err)
+ err = sock->ops->sendmsg(iocb, sock, msg, size);
+
+ if (err >= 0 && sock->sk) { /* ATOP */
+ switch (sock->sk->sk_family) { /* ATOP */
+ case PF_INET: /* ATOP */
+ case PF_INET6: /* ATOP */
+ switch (sock->sk->sk_type) { /* ATOP */
+ case SOCK_STREAM: /* ATOP */
+ current->group_leader->stat.tcp_snd++; /* ATOP */
+ current->group_leader->stat.tcp_ssz+=size;/* ATOP */
+ break; /* ATOP */
+ case SOCK_DGRAM: /* ATOP */
+ current->group_leader->stat.udp_snd++; /* ATOP */
+ current->group_leader->stat.udp_ssz+=size;/* ATOP */
+ break; /* ATOP */
+ case SOCK_RAW: /* ATOP */
+ current->group_leader->stat.raw_snd++; /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ return err;
}
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
@@ -682,7 +700,29 @@ static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
{
int err = security_socket_recvmsg(sock, msg, size, flags);
- return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
+ if (!err)
+ err = __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
+
+ if (err >= 0 && sock->sk) { /* ATOP */
+ switch (sock->sk->sk_family) { /* ATOP */
+ case PF_INET: /* ATOP */
+ case PF_INET6: /* ATOP */
+ switch (sock->sk->sk_type) { /* ATOP */
+ case SOCK_STREAM: /* ATOP */
+ current->group_leader->stat.tcp_rcv++; /* ATOP */
+ current->group_leader->stat.tcp_rsz+=err; /* ATOP */
+ break; /* ATOP */
+ case SOCK_DGRAM: /* ATOP */
+ current->group_leader->stat.udp_rcv++; /* ATOP */
+ current->group_leader->stat.udp_rsz+=err; /* ATOP */
+ break; /* ATOP */
+ case SOCK_RAW: /* ATOP */
+ current->group_leader->stat.raw_rcv++; /* ATOP */
+ break; /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ } /* ATOP */
+ return err;
}
int sock_recvmsg(struct socket *sock, struct msghdr *msg,

View File

@ -0,0 +1,125 @@
Index: linux-2.6.28/include/linux/acct.h
===================================================================
--- linux-2.6.28.orig/include/linux/acct.h 2009-01-14 13:02:24.000000000 +0100
+++ linux-2.6.28/include/linux/acct.h 2009-01-14 13:03:33.000000000 +0100
@@ -97,6 +97,54 @@
char ac_comm[ACCT_COMM]; /* Command Name */
};
+struct acct_atop
+{
+ char ac_flag; /* Flags */
+ char ac_version; /* Always set to ACCT_VERSION */
+ __u32 ac_pid; /* Process ID */
+ __u32 ac_ppid; /* Parent Process ID */
+ __u16 ac_uid16; /* LSB of Real User ID */
+ __u16 ac_gid16; /* LSB of Real Group ID */
+ __u16 ac_tty; /* Control Terminal */
+ __u32 ac_btime; /* Process Creation Time */
+ comp_t ac_utime; /* User Time */
+ comp_t ac_stime; /* System Time */
+ comp_t ac_etime; /* Elapsed Time */
+ comp_t ac_mem; /* Virtual Memory */
+ comp_t ac_rss; /* Resident Memory */
+ comp_t ac_io; /* Chars Transferred */
+ comp_t ac_rw; /* Blocks Read or Written */
+ comp_t ac_bread; /* Blocks Read */
+ comp_t ac_bwrite; /* Blocks Written */
+ comp2_t ac_dskrsz; /* Cum. blocks read */
+ comp2_t ac_dskwsz; /* Cum. blocks written */
+ comp_t ac_tcpsnd; /* TCP send requests */
+ comp_t ac_tcprcv; /* TCP recv requests */
+ comp2_t ac_tcpssz; /* TCP cum. length */
+ comp2_t ac_tcprsz; /* TCP cum. length */
+ comp_t ac_udpsnd; /* UDP send requests */
+ comp_t ac_udprcv; /* UDP recv requests */
+ comp2_t ac_udpssz; /* UDP cum. length */
+ comp2_t ac_udprsz; /* UDP cum. length */
+ comp_t ac_rawsnd; /* RAW send requests */
+ comp_t ac_rawrcv; /* RAW recv requests */
+ comp_t ac_minflt; /* Minor Pagefaults */
+ comp_t ac_majflt; /* Major Pagefaults */
+ comp_t ac_swaps; /* Number of Swaps */
+/* m68k had no padding here. */
+#if !defined(CONFIG_M68K) || !defined(__KERNEL__)
+ __u16 ac_ahz; /* AHZ */
+#endif
+ __u32 ac_exitcode; /* Exitcode */
+ char ac_comm[ACCT_COMM + 1]; /* Command Name */
+ __u8 ac_etime_hi; /* Elapsed Time MSB */
+ __u16 ac_etime_lo; /* Elapsed Time LSB */
+ __u32 ac_uid; /* Real User ID */
+ __u32 ac_gid; /* Real Group ID */
+};
+
+
+
/*
* accounting flags
*/
@@ -146,7 +194,13 @@
* 5: new binary incompatible format (128 bytes, second half)
*
*/
+#define CONFIG_PROCESS_ACCT_ATOP
+#ifdef CONFIG_PROCESS_ACCT_ATOP
+#define ACCT_VERSION 6
+#define AHZ (USER_HZ)
+typedef struct acct_atop acct_t;
+#else
#ifdef CONFIG_BSD_PROCESS_ACCT_V3
#define ACCT_VERSION 3
#define AHZ 100
@@ -160,6 +214,7 @@
#define AHZ (USER_HZ)
typedef struct acct acct_t;
#endif
+#endif
#else
#define ACCT_VERSION 2
Index: linux-2.6.28/kernel/acct.c
===================================================================
--- linux-2.6.28.orig/kernel/acct.c 2009-01-14 13:03:31.000000000 +0100
+++ linux-2.6.28/kernel/acct.c 2009-01-14 13:03:33.000000000 +0100
@@ -405,7 +405,7 @@
return exp;
}
-#if ACCT_VERSION==1 || ACCT_VERSION==2
+#if ACCT_VERSION==1 || ACCT_VERSION==2 || ACCT_VERSION==6
/*
* encode an u64 into a comp2_t (24 bits)
*
@@ -552,6 +552,30 @@
ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns);
rcu_read_unlock();
#endif
+#if ACCT_VERSION==6 /* ATOP */
+ ac.ac_pid = current->pid;
+ ac.ac_ppid = current->parent->pid;
+ ac.ac_uid16 = ac.ac_uid;
+ ac.ac_gid16 = ac.ac_gid;
+ ac.ac_ahz = AHZ;
+ ac.ac_bread = encode_comp_t(current->stat.dsk_rio);
+ ac.ac_bwrite = encode_comp_t(current->stat.dsk_wio);
+ ac.ac_dskrsz = encode_comp2_t(current->stat.dsk_rsz);
+ ac.ac_dskwsz = encode_comp2_t(current->stat.dsk_wsz);
+ ac.ac_tcpsnd = encode_comp_t(current->stat.tcp_snd);
+ ac.ac_tcprcv = encode_comp_t(current->stat.tcp_rcv);
+ ac.ac_tcpssz = encode_comp2_t(current->stat.tcp_ssz);
+ ac.ac_tcprsz = encode_comp2_t(current->stat.tcp_rsz);
+ ac.ac_udpsnd = encode_comp_t(current->stat.udp_snd);
+ ac.ac_udprcv = encode_comp_t(current->stat.udp_rcv);
+ ac.ac_udpssz = encode_comp2_t(current->stat.udp_ssz);
+ ac.ac_udprsz = encode_comp2_t(current->stat.udp_rsz);
+ ac.ac_rawsnd = encode_comp_t(current->stat.raw_snd);
+ ac.ac_rawrcv = encode_comp_t(current->stat.raw_rcv);
+ ac.ac_rss = current->mm ?
+ encode_comp_t(get_mm_rss(current->mm)<<(PAGE_SHIFT-10)) :
+ encode_comp_t(0);
+#endif
spin_lock_irq(&current->sighand->siglock);
tty = current->signal->tty; /* Safe as we hold the siglock */

8782
3.3.8/3.3-ck1.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
3rdparty/mkbuild.pl | 92 +++++++++++++++++++++++++++++++++++++++++++++
Documentation/3rdparty.txt | 76 +++++++++++++++++++++++++++++++++++++
2 files changed, 168 insertions(+)
diff -Nurp linux-2.6.37/3rdparty/mkbuild.pl 3rdparty/mkbuild.pl
--- linux-2.6.37/3rdparty/mkbuild.pl 1970-01-01 02:00:00.000000000 +0200
+++ 3rdparty/mkbuild.pl 2004-04-23 14:59:03.000000000 +0300
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+#
+# Version 1.0
+#
+# Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+# Copyright 2002 Juan Quintela <quintela@mandrakesoft.com>
+# Copyright 2003 Nicolas Planel <nplanel@mandrakesoft.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+#
+#
+# Run "mkbuild.pl"
+#
+# This program generates the following files
+# Makefile
+# Makefile.drivers
+# Config.in
+# using the information in the subdirs of this directory.
+#
+# subdirs need to have:
+# a Config.in file
+# a Makefile with a O_TARGET/L_TARGET targets
+# The config.in should set a CONFIG_<module_dir_name> to m/y.
+
+use strict;
+
+opendir(THISDIR, ".");
+# get dirs without . and .. garbage
+my (@modules) = grep(!/\.\.?$/,grep(-d, readdir(THISDIR)));
+closedir(THISDIR);
+
+generate_kconfig(@modules);
+generate_makefile(@modules);
+exit(0);
+
+##########################################################################
+
+sub generate_makefile {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Makefile" or die "Cannot create new Makefile: $!\n";
+ print F <<'EOM';
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+EOM
+ printf F "obj- := 3rdparty.o # Dummy rule to force built-in.o to be made\n";
+ printf F "obj-\$(%s) += %s\n", to_CONFIG($_), $_ . '/' foreach @modules;
+}
+
+sub generate_kconfig {
+ my (@modules) = @_;
+
+ local *F;
+ open F, "> Kconfig" or die "Cannot create Kconfig: $!\n";
+ print F <<"EOM";
+#
+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
+#
+
+menu "Unofficial 3rd party kernel additions"
+
+EOM
+
+ foreach (@modules) {
+ die "No Kconfig in $_.\n" if ! -r "$_/Kconfig";
+ print F "source 3rdparty/$_/Kconfig\n";
+ }
+ print F "\n\nendmenu\n";
+}
+
+sub to_CONFIG {
+ local $_ = $_[0];
+ tr/a-z/A-Z/;
+ s/[\-\. ]/_/g;
+ "CONFIG_$_";
+}
+
+sub find_target {
+ my ($module_dir) = @_;
+
+ local *F;
+ open(F, "$module_dir/Makefile") or die "$module_dir/Makefile: $!\n";
+ while (<F>) {
+ chomp;
+ return $1 if (/[LO]_TARGET.*:=\s+(\S+)/);
+ }
+}
+
diff -Nurp linux-2.6.37/Documentation/3rdparty.txt Documentation/3rdparty.txt
--- linux-2.6.37/Documentation/3rdparty.txt 1970-01-01 02:00:00.000000000 +0200
+++ Documentation/3rdparty.txt 2003-11-22 01:07:26.000000000 +0200
@@ -0,0 +1,76 @@
+
+Third-Party Kernel Source Module Support, or
+an easy way to add modules to your kernel build.
+
+
+
+Vendors quite often add additional drivers and features to the kernel
+which require nothing more than modifying Kconfig, Makefile, and
+adding one or more files to a sub-directory. As a single discrete task,
+this is not a problem. However, using patches to add modules to the
+kernel very often results in patch conflicts, resulting in needless time
+wastage as developers regenerate an otherwise working kernel patch.
+
+This is designed as a solution to these problems. It is NOT designed as
+a replacement for the kernel build system, but merely as a tool for
+vendors and system administrators to ease the pain of patch management.
+
+The key feature of this system is the distinct lack of patches. Drivers
+are installed via unpacking a tarball.
+
+
+
+Adding a directory to the build (usually from a tarball)
+--------------------------------------------------------
+If a directory exists inside the 3rdparty sub-directory that contains a
+proper Makefile, it can be added to the build. It also needs a
+Kconfig file.
+
+ cd /usr/src/linux-2.4.3/3rdparty
+ bzcat /tmp/my-driver2.tar.bz2 | tar xf - # creates "my2" dir
+
+
+Limitations
+-----------
+There are some limitations to this system. This system is only
+designed to support a very common case. If you find yourself running
+into limitations (kernel build experts can spot them right off),
+then you should probably be patching the kernel instead of using
+mkbuild.pl for that particular module.
+
+FIXME: actually list the limitations
+
+
+
+Other notes
+-----------
+Link order is controlled by the order of mkbuild.pl executions.
+
+"make mrproper" will erase Makefile.meta, and empty Kconfig, Makefile,
+and Makefile.drivers.
+
+IMPORTANT NOTE: Because this feature modifies the kernel's makefiles and
+configuration system, you MUST complete all mkbuild.pl runs before
+running any "make" command.
+
+Building in the 3rdparty dir
+----------------------------
+
+If you use modules that:
+ - are contained in one subdir with the name of the module
+ - has a Makefile
+ - has a Kconfig file
+
+The system calls the ./mkbuild.pl script. It will search for
+subdirectories, and will try to build each of them as a module.
+Things to note:
+
+ The dependencies will be done in a module called:
+
+ 3rdparty/<module_dir_name>/<module_name>
+
+depending of CONFIG_<module_name_in_uppercase>.
+
+<module_name> is the value of O_TARGET/L_TARGET.
+
+

View File

@ -0,0 +1,372 @@
Submitted By: Mario Fetka (mario dot fetka at gmail dot com)
Date: 2012-11-18
Initial Package Version: 3.2.33
Origin: openwtr.org packages/system/button-hotplug
Upstream Status: unknown
Description: create uevents from button usage
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/Kconfig 3rdparty/button_hotplug/Kconfig
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/Kconfig 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/Kconfig 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,2 @@
+config BUTTON_HOTPLUG
+ tristate "Button Hotplug driver"
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/Makefile 3rdparty/button_hotplug/Makefile
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/Makefile 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1 @@
+obj-${CONFIG_BUTTON_HOTPLUG} += button-hotplug.o
\ No newline at end of file
diff -Naur linux-3.2.33-go.orig/3rdparty/button_hotplug/button-hotplug.c 3rdparty/button_hotplug/button-hotplug.c
--- linux-3.2.33-go.orig/3rdparty/button_hotplug/button-hotplug.c 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/button_hotplug/button-hotplug.c 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,349 @@
+/*
+ * Button Hotplug driver
+ *
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+#include <linux/input.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+
+#define DRV_NAME "button-hotplug"
+#define DRV_VERSION "0.4.1"
+#define DRV_DESC "Button Hotplug driver"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+#ifndef BIT_MASK
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#endif
+
+struct bh_priv {
+ unsigned long *seen;
+ struct input_handle handle;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = handle->private;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen[btn]) / HZ, value);
+ priv->seen[btn] = seen;
+}
+#else
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+static int button_hotplug_connect(struct input_handler *handler,
+ struct input_dev *dev, const struct input_device_id *id)
+{
+ struct bh_priv *priv;
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (test_bit(button_map[i].code, dev->keybit))
+ break;
+
+ if (i == ARRAY_SIZE(button_map))
+ return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv) +
+ (sizeof(unsigned long) * ARRAY_SIZE(button_map)),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->seen = (unsigned long *) &priv[1];
+ priv->handle.private = priv;
+ priv->handle.dev = dev;
+ priv->handle.handler = handler;
+ priv->handle.name = DRV_NAME;
+
+ ret = input_register_handle(&priv->handle);
+ if (ret)
+ goto err_free_priv;
+
+ ret = input_open_device(&priv->handle);
+ if (ret)
+ goto err_unregister_handle;
+
+ BH_DBG("connected to %s\n", dev->name);
+
+ return 0;
+
+ err_unregister_handle:
+ input_unregister_handle(&priv->handle);
+
+ err_free_priv:
+ kfree(priv);
+ return ret;
+}
+
+static void button_hotplug_disconnect(struct input_handle *handle)
+{
+ struct bh_priv *priv = handle->private;
+
+ input_close_device(handle);
+ input_unregister_handle(handle);
+
+ kfree(priv);
+}
+
+static const struct input_device_id button_hotplug_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ },
+ {
+ /* Terminating entry */
+ },
+};
+
+MODULE_DEVICE_TABLE(input, button_hotplug_ids);
+
+static struct input_handler button_hotplug_handler = {
+ .event = button_hotplug_event,
+ .connect = button_hotplug_connect,
+ .disconnect = button_hotplug_disconnect,
+ .name = DRV_NAME,
+ .id_table = button_hotplug_ids,
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int __init button_hotplug_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+ ret = input_register_handler(&button_hotplug_handler);
+ if (ret)
+ BH_ERR("unable to register input handler\n");
+
+ return ret;
+}
+module_init(button_hotplug_init);
+
+static void __exit button_hotplug_exit(void)
+{
+ input_unregister_handler(&button_hotplug_handler);
+}
+module_exit(button_hotplug_exit);
+
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+

View File

@ -0,0 +1,472 @@
Submitted By: Mario Fetka (mario dot fetka at gmail dot com)
Date: 2012-11-18
Initial Package Version: 3.2.33
Origin: openwtr.org packages/system/gpio-button-hotplug
Upstream Status: unknown
Description: gpio button uevent
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Kconfig 3rdparty/gpio_button_hotplug/Kconfig
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Kconfig 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/Kconfig 2012-11-18 18:41:43.048939468 +0000
@@ -0,0 +1,2 @@
+config GPIO_BUTTON_HOTPLUG
+ tristate "GPIO Button Hotplug driver"
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Makefile 3rdparty/gpio_button_hotplug/Makefile
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/Makefile 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1 @@
+obj-${CONFIG_GPIO_BUTTON_HOTPLUG} += gpio-button-hotplug.o
diff -Naur linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 3rdparty/gpio_button_hotplug/gpio-button-hotplug.c
--- linux-3.2.33-go.orig/3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 1970-01-01 00:00:00.000000000 +0000
+++ 3rdparty/gpio_button_hotplug/gpio-button-hotplug.c 2012-11-18 14:45:26.000000000 +0000
@@ -0,0 +1,450 @@
+/*
+ * GPIO Button Hotplug driver
+ *
+ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#define DRV_NAME "gpio-keys-polled"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+struct bh_priv {
+ unsigned long seen;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+struct gpio_keys_button_data {
+ struct delayed_work work;
+ struct bh_priv bh;
+ int last_state;
+ int count;
+ int threshold;
+ int can_sleep;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = &data->bh;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen) / HZ, value);
+ priv->seen = seen;
+}
+#else
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+struct gpio_keys_polled_dev {
+ struct delayed_work work;
+
+ struct device *dev;
+ struct gpio_keys_platform_data *pdata;
+ struct gpio_keys_button_data data[0];
+};
+
+static void gpio_keys_polled_check_state(struct gpio_keys_button *button,
+ struct gpio_keys_button_data *bdata)
+{
+ int state;
+
+ if (bdata->can_sleep)
+ state = !!gpio_get_value_cansleep(button->gpio);
+ else
+ state = !!gpio_get_value(button->gpio);
+
+ state = !!(state ^ button->active_low);
+ if (state != bdata->last_state) {
+ unsigned int type = button->type ?: EV_KEY;
+
+ button_hotplug_event(bdata, type, button->code, state);
+ bdata->count = 0;
+ bdata->last_state = state;
+ }
+}
+
+static void gpio_keys_polled_queue_work(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ unsigned long delay = msecs_to_jiffies(pdata->poll_interval);
+
+ if (delay >= HZ)
+ delay = round_jiffies_relative(delay);
+ schedule_delayed_work(&bdev->work, delay);
+}
+
+static void gpio_keys_polled_poll(struct work_struct *work)
+{
+ struct gpio_keys_polled_dev *bdev =
+ container_of(work, struct gpio_keys_polled_dev, work.work);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ for (i = 0; i < bdev->pdata->nbuttons; i++) {
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+ if (bdata->count < bdata->threshold)
+ bdata->count++;
+ else
+ gpio_keys_polled_check_state(&pdata->buttons[i], bdata);
+ }
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devinit gpio_keys_polled_open(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ if (pdata->enable)
+ pdata->enable(bdev->dev);
+
+ /* report initial state of the buttons */
+ for (i = 0; i < pdata->nbuttons; i++)
+ gpio_keys_polled_check_state(&pdata->buttons[i], &bdev->data[i]);
+
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devexit gpio_keys_polled_close(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+ cancel_delayed_work_sync(&bdev->work);
+
+ if (pdata->disable)
+ pdata->disable(bdev->dev);
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct gpio_keys_polled_dev *bdev;
+ int error;
+ int i;
+
+ if (!pdata || !pdata->poll_interval)
+ return -EINVAL;
+
+ bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+ pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+ GFP_KERNEL);
+ if (!bdev) {
+ dev_err(dev, "no memory for private data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+ unsigned int gpio = button->gpio;
+
+ if (button->wakeup) {
+ dev_err(dev, DRV_NAME " does not support wakeup\n");
+ error = -EINVAL;
+ goto err_free_gpio;
+ }
+
+ error = gpio_request(gpio,
+ button->desc ? button->desc : DRV_NAME);
+ if (error) {
+ dev_err(dev, "unable to claim gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ error = gpio_direction_input(gpio);
+ if (error) {
+ dev_err(dev,
+ "unable to set direction on gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ bdata->can_sleep = gpio_cansleep(gpio);
+ bdata->last_state = 0;
+ bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+ pdata->poll_interval);
+ }
+
+ bdev->dev = &pdev->dev;
+ bdev->pdata = pdata;
+ platform_set_drvdata(pdev, bdev);
+
+ INIT_DELAYED_WORK(&bdev->work, gpio_keys_polled_poll);
+
+ gpio_keys_polled_open(bdev);
+
+ return 0;
+
+err_free_gpio:
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+ struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i = pdata->nbuttons;
+
+ gpio_keys_polled_close(bdev);
+
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+ .probe = gpio_keys_polled_probe,
+ .remove = __devexit_p(gpio_keys_polled_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+ return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+ platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons hotplug driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
diff -uNr linux-3.2.33-go.orig/arch/alpha/Kconfig linux-3.2.33-go/arch/alpha/Kconfig
--- linux-3.2.33-go.orig/arch/alpha/Kconfig 2012-11-15 22:08:02.768806792 +0100
+++ linux-3.2.33-go/arch/alpha/Kconfig 2012-11-15 22:08:29.937483632 +0100
@@ -673,3 +673,4 @@
source "lib/Kconfig"
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/arm/Kconfig linux-3.2.33-go/arch/arm/Kconfig
--- linux-3.2.33-go.orig/arch/arm/Kconfig 2012-11-15 22:07:59.952839378 +0100
+++ linux-3.2.33-go/arch/arm/Kconfig 2012-11-15 22:14:01.950566716 +0100
@@ -2259,3 +2259,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/ia64/Kconfig linux-3.2.33-go/arch/ia64/Kconfig
--- linux-3.2.33-go.orig/arch/ia64/Kconfig 2012-11-15 22:08:00.893828523 +0100
+++ linux-3.2.33-go/arch/ia64/Kconfig 2012-11-15 22:08:29.938483621 +0100
@@ -669,3 +669,5 @@
config IOMMU_HELPER
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/mips/Kconfig linux-3.2.33-go/arch/mips/Kconfig
--- linux-3.2.33-go.orig/arch/mips/Kconfig 2012-11-15 22:08:02.698807597 +0100
+++ linux-3.2.33-go/arch/mips/Kconfig 2012-11-15 22:08:29.939483610 +0100
@@ -2485,3 +2485,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/powerpc/Kconfig linux-3.2.33-go/arch/powerpc/Kconfig
--- linux-3.2.33-go.orig/arch/powerpc/Kconfig 2012-11-15 22:08:01.893816938 +0100
+++ linux-3.2.33-go/arch/powerpc/Kconfig 2012-11-15 22:08:29.940483598 +0100
@@ -980,3 +980,5 @@
bool
source "arch/powerpc/kvm/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/sparc/Kconfig linux-3.2.33-go/arch/sparc/Kconfig
--- linux-3.2.33-go.orig/arch/sparc/Kconfig 2012-11-15 22:08:00.130837331 +0100
+++ linux-3.2.33-go/arch/sparc/Kconfig 2012-11-15 22:08:29.941483586 +0100
@@ -605,3 +605,5 @@
source "crypto/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/arch/x86/Kconfig linux-3.2.33-go/arch/x86/Kconfig
--- linux-3.2.33-go.orig/arch/x86/Kconfig 2012-11-15 22:08:00.435833823 +0100
+++ linux-3.2.33-go/arch/x86/Kconfig 2012-11-15 22:08:29.945483540 +0100
@@ -2179,3 +2179,5 @@
source "arch/x86/kvm/Kconfig"
source "lib/Kconfig"
+
+source "3rdparty/Kconfig"
diff -uNr linux-3.2.33-go.orig/Makefile linux-3.2.33-go/Makefile
--- linux-3.2.33-go.orig/Makefile 2012-11-15 22:08:03.435799123 +0100
+++ linux-3.2.33-go/Makefile 2012-11-15 22:08:29.946483529 +0100
@@ -507,7 +507,7 @@
# Objects we will link into vmlinux / subdirs we need to visit
init-y := init/
-drivers-y := drivers/ sound/ firmware/
+drivers-y := drivers/ sound/ firmware/ 3rdparty/
net-y := net/
libs-y := lib/
core-y := usr/
diff -uNr linux-3.2.33-go.orig/scripts/kconfig/Makefile linux-3.2.33-go/scripts/kconfig/Makefile
--- linux-3.2.33-go.orig/scripts/kconfig/Makefile 2012-11-15 22:07:58.064861094 +0100
+++ linux-3.2.33-go/scripts/kconfig/Makefile 2012-11-15 22:08:55.603180188 +0100
@@ -11,29 +11,29 @@
Kconfig := Kconfig
endif
-xconfig: $(obj)/qconf
+xconfig: $(obj)/qconf 3rdparty/Makefile
$< $(Kconfig)
-gconfig: $(obj)/gconf
+gconfig: $(obj)/gconf 3rdparty/Makefile
$< $(Kconfig)
-menuconfig: $(obj)/mconf
+menuconfig: $(obj)/mconf 3rdparty/Makefile
$< $(Kconfig)
-config: $(obj)/conf
+config: $(obj)/conf 3rdparty/Makefile
$< --oldaskconfig $(Kconfig)
-nconfig: $(obj)/nconf
+nconfig: $(obj)/nconf 3rdparty/Makefile
$< $(Kconfig)
-oldconfig: $(obj)/conf
+oldconfig: $(obj)/conf 3rdparty/Makefile
$< --$@ $(Kconfig)
-silentoldconfig: $(obj)/conf
+silentoldconfig: $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/generated
$< --$@ $(Kconfig)
-localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 3rdparty/Makefile
$(Q)mkdir -p include/generated
$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
$(Q)if [ -f .config ]; then \
@@ -90,18 +90,18 @@
*) cat $(CLONECONFIG) > .config.running ;; \
esac && \
echo -e "Cloning configuration file $(CLONECONFIG)\n"
- $(Q)$< --defconfig=.config.running arch/$(SRCARCH)/Kconfig
+ $(Q)$< --defconfig=.config.running arch/$(SRCARCH)/Kconfig 3rdparty/Makefile
PHONY += listnewconfig oldnoconfig savedefconfig defconfig
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig oldnoconfig: $(obj)/conf 3rdparty/Makefile
$< --$@ $(Kconfig)
-savedefconfig: $(obj)/conf
+savedefconfig: $(obj)/conf 3rdparty/Makefile
$< --$@=defconfig $(Kconfig)
-defconfig: $(obj)/conf
+defconfig: $(obj)/conf 3rdparty/Makefile
ifeq ($(KBUILD_DEFCONFIG),)
$< --defconfig $(Kconfig)
else
@@ -109,7 +109,7 @@
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
endif
-%_defconfig: $(obj)/conf
+%_defconfig: $(obj)/conf 3rdparty/Makefile
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
# Help text used by make help
@@ -186,6 +186,8 @@
gconf-target := 1
endif
+3rdparty/Makefile:
+ pushd $(srctree)/3rdparty ; $(PERL) ./mkbuild.pl ; popd
ifeq ($(qconf-target),1)
hostprogs-y += qconf

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
--- a/include/linux/netfilter/xt_layer7.h
+++ b/include/linux/netfilter/xt_layer7.h
@@ -8,6 +8,7 @@ struct xt_layer7_info {
char protocol[MAX_PROTOCOL_LEN];
char pattern[MAX_PATTERN_LEN];
u_int8_t invert;
+ u_int8_t pkt;
};
#endif /* _XT_LAYER7_H */
--- a/net/netfilter/xt_layer7.c
+++ b/net/netfilter/xt_layer7.c
@@ -314,33 +314,35 @@ static int match_no_append(struct nf_con
}
/* add the new app data to the conntrack. Return number of bytes added. */
-static int add_data(struct nf_conn * master_conntrack,
- char * app_data, int appdatalen)
+static int add_datastr(char *target, int offset, char *app_data, int len)
{
int length = 0, i;
- int oldlength = master_conntrack->layer7.app_data_len;
-
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
- clear on whether the race condition exists or whether this really
- fixes it. I might just be being dense... Anyway, if it's not really
- a fix, all it does is waste a very small amount of time. */
- if(!master_conntrack->layer7.app_data) return 0;
+ if (!target) return 0;
/* Strip nulls. Make everything lower case (our regex lib doesn't
do case insensitivity). Add it to the end of the current data. */
- for(i = 0; i < maxdatalen-oldlength-1 &&
- i < appdatalen; i++) {
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
if(app_data[i] != '\0') {
/* the kernel version of tolower mungs 'upper ascii' */
- master_conntrack->layer7.app_data[length+oldlength] =
+ target[length+offset] =
isascii(app_data[i])?
tolower(app_data[i]) : app_data[i];
length++;
}
}
+ target[length+offset] = '\0';
+
+ return length;
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_data(struct nf_conn * master_conntrack,
+ char * app_data, int appdatalen)
+{
+ int length;
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
- master_conntrack->layer7.app_data_len = length + oldlength;
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
+ master_conntrack->layer7.app_data_len += length;
return length;
}
@@ -438,7 +440,7 @@ match(const struct sk_buff *skbin,
enum ip_conntrack_info master_ctinfo, ctinfo;
struct nf_conn *master_conntrack, *conntrack;
- unsigned char * app_data;
+ unsigned char *app_data, *tmp_data;
unsigned int pattern_result, appdatalen;
regexp * comppattern;
@@ -466,8 +468,8 @@ match(const struct sk_buff *skbin,
master_conntrack = master_ct(master_conntrack);
/* if we've classified it or seen too many packets */
- if(total_acct_packets(master_conntrack) > num_packets ||
- master_conntrack->layer7.app_proto) {
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
+ master_conntrack->layer7.app_proto)) {
pattern_result = match_no_append(conntrack, master_conntrack,
ctinfo, master_ctinfo, info);
@@ -500,6 +502,25 @@ match(const struct sk_buff *skbin,
/* the return value gets checked later, when we're ready to use it */
comppattern = compile_and_cache(info->pattern, info->protocol);
+ if (info->pkt) {
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
+ if(!tmp_data){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ return info->invert;
+ }
+
+ tmp_data[0] = '\0';
+ add_datastr(tmp_data, 0, app_data, appdatalen);
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
+
+ kfree(tmp_data);
+ tmp_data = NULL;
+ spin_unlock_bh(&l7_lock);
+
+ return (pattern_result ^ info->invert);
+ }
+
/* On the first packet of a connection, allocate space for app data */
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
!master_conntrack->layer7.app_data){

View File

@ -0,0 +1,51 @@
--- a/net/netfilter/xt_layer7.c
+++ b/net/netfilter/xt_layer7.c
@@ -415,7 +415,9 @@ static int layer7_write_proc(struct file
}
static bool
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+match(const struct sk_buff *skbin, struct xt_action_param *par)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
match(const struct sk_buff *skbin, const struct xt_match_param *par)
#else
match(const struct sk_buff *skbin,
@@ -597,14 +599,19 @@ match(const struct sk_buff *skbin,
}
// load nf_conntrack_ipv4
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+static int
+#else
+static bool
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
-static bool check(const struct xt_mtchk_param *par)
+check(const struct xt_mtchk_param *par)
{
if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", par->match->family);
#else
-static bool check(const char *tablename, const void *inf,
+check(const char *tablename, const void *inf,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
@@ -612,9 +619,15 @@ static bool check(const char *tablename,
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return -EINVAL;
+ }
+ return 0;
+#else
return 0;
}
return 1;
+#endif
}

View File

@ -0,0 +1,61 @@
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -857,6 +857,27 @@ config NETFILTER_XT_MATCH_IPVS
If unsure, say N.
+config NETFILTER_XT_MATCH_LAYER7
+ tristate '"layer7" match support'
+ depends on EXPERIMENTAL
+ depends on NETFILTER_XTABLES
+ depends on NETFILTER_ADVANCED
+ depends on NF_CONNTRACK
+ help
+ Say Y if you want to be able to classify connections (and their
+ packets) based on regular expression matching of their application
+ layer data. This is one way to classify applications such as
+ peer-to-peer filesharing systems that do not always use the same
+ port.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+ bool 'Layer 7 debugging output'
+ depends on NETFILTER_XT_MATCH_LAYER7
+ help
+ Say Y to get lots of debugging output.
+
config NETFILTER_XT_MATCH_LENGTH
tristate '"length" match support'
depends on NETFILTER_ADVANCED
@@ -1053,26 +1074,11 @@ config NETFILTER_XT_MATCH_STATE
To compile it as a module, choose M here. If unsure, say N.
-config NETFILTER_XT_MATCH_LAYER7
- tristate '"layer7" match support'
- depends on NETFILTER_XTABLES
- depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK)
- depends on NETFILTER_ADVANCED
- help
- Say Y if you want to be able to classify connections (and their
- packets) based on regular expression matching of their application
- layer data. This is one way to classify applications such as
- peer-to-peer filesharing systems that do not always use the same
- port.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config NETFILTER_XT_MATCH_LAYER7_DEBUG
- bool 'Layer 7 debugging output'
- depends on NETFILTER_XT_MATCH_LAYER7
- help
- Say Y to get lots of debugging output.
-
+ bool 'Layer 7 debugging output'
+ depends on NETFILTER_XT_MATCH_LAYER7
+ help
+ Say Y to get lots of debugging output.
config NETFILTER_XT_MATCH_STATISTIC
tristate '"statistic" match support'

View File

@ -0,0 +1,118 @@
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -2,12 +2,15 @@
#define __NF_CONNTRACK_SIP_H__
#ifdef __KERNEL__
+#include <linux/types.h>
+
#define SIP_PORT 5060
#define SIP_TIMEOUT 3600
struct nf_ct_sip_master {
unsigned int register_cseq;
unsigned int invite_cseq;
+ __be16 forced_dport;
};
enum sip_expectation_classes {
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -73,6 +73,7 @@ static int map_addr(struct sk_buff *skb,
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ struct nf_conn_help *help = nfct_help(ct);
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
unsigned int buflen;
__be32 newaddr;
@@ -85,7 +86,8 @@ static int map_addr(struct sk_buff *skb,
} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
- newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
+ newport = help->help.ct_sip_info.forced_dport ? :
+ ct->tuplehash[!dir].tuple.src.u.udp.port;
} else
return 1;
@@ -121,6 +123,7 @@ static unsigned int ip_nat_sip(struct sk
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ struct nf_conn_help *help = nfct_help(ct);
unsigned int coff, matchoff, matchlen;
enum sip_header_types hdr;
union nf_inet_addr addr;
@@ -229,6 +232,20 @@ next:
!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
return NF_DROP;
+ /* Mangle destination port for Cisco phones, then fix up checksums */
+ if (dir == IP_CT_DIR_REPLY && help->help.ct_sip_info.forced_dport) {
+ struct udphdr *uh;
+
+ if (!skb_make_writable(skb, skb->len))
+ return NF_DROP;
+
+ uh = (struct udphdr *)(skb->data + ip_hdrlen(skb));
+ uh->dest = help->help.ct_sip_info.forced_dport;
+
+ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 0, 0, NULL, 0))
+ return NF_DROP;
+ }
+
return NF_ACCEPT;
}
@@ -280,8 +297,10 @@ static unsigned int ip_nat_sip_expect(st
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ struct nf_conn_help *help = nfct_help(ct);
__be32 newip;
u_int16_t port;
+ __be16 srcport;
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
unsigned buflen;
@@ -294,8 +313,9 @@ static unsigned int ip_nat_sip_expect(st
/* If the signalling port matches the connection's source port in the
* original direction, try to use the destination port in the opposite
* direction. */
- if (exp->tuple.dst.u.udp.port ==
- ct->tuplehash[dir].tuple.src.u.udp.port)
+ srcport = help->help.ct_sip_info.forced_dport ? :
+ ct->tuplehash[dir].tuple.src.u.udp.port;
+ if (exp->tuple.dst.u.udp.port == srcport)
port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
else
port = ntohs(exp->tuple.dst.u.udp.port);
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1363,8 +1363,25 @@ static int process_sip_request(struct sk
{
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ struct nf_conn_help *help = nfct_help(ct);
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
unsigned int matchoff, matchlen;
unsigned int cseq, i;
+ union nf_inet_addr addr;
+ __be16 port;
+
+ /* Many Cisco IP phones use a high source port for SIP requests, but
+ * listen for the response on port 5060. If we are the local
+ * router for one of these phones, save the port number from the
+ * Via: header so that nf_nat_sip can redirect the responses to
+ * the correct port.
+ */
+ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
+ SIP_HDR_VIA_UDP, NULL, &matchoff,
+ &matchlen, &addr, &port) > 0 &&
+ port != ct->tuplehash[dir].tuple.src.u.udp.port &&
+ nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
+ help->help.ct_sip_info.forced_dport = port;
for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
const struct sip_handler *handler;

View File

@ -0,0 +1,93 @@
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -93,6 +93,7 @@ struct ipt_ip {
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
/* Values for "inv" field in struct ipt_ip. */
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -81,6 +81,9 @@ ip_packet_match(const struct iphdr *ip,
#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
+ return true;
+
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) ||
FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
@@ -134,6 +137,29 @@ ip_packet_match(const struct iphdr *ip,
return true;
}
+static void
+ip_checkdefault(struct ipt_ip *ip)
+{
+ static const char iface_mask[IFNAMSIZ] = {};
+
+ if (ip->invflags || ip->flags & IPT_F_FRAG)
+ return;
+
+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
+ return;
+
+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+ return;
+
+ if (ip->smsk.s_addr || ip->dmsk.s_addr)
+ return;
+
+ if (ip->proto)
+ return;
+
+ ip->flags |= IPT_F_NO_DEF_MATCH;
+}
+
static bool
ip_checkentry(const struct ipt_ip *ip)
{
@@ -561,7 +587,7 @@ static void cleanup_match(struct xt_entr
}
static int
-check_entry(const struct ipt_entry *e, const char *name)
+check_entry(struct ipt_entry *e, const char *name)
{
const struct xt_entry_target *t;
@@ -570,6 +596,8 @@ check_entry(const struct ipt_entry *e, c
return -EINVAL;
}
+ ip_checkdefault(&e->ip);
+
if (e->target_offset + sizeof(struct xt_entry_target) >
e->next_offset)
return -EINVAL;
@@ -931,6 +959,7 @@ copy_entries_to_user(unsigned int total_
const struct xt_table_info *private = table->private;
int ret = 0;
const void *loc_cpu_entry;
+ u8 flags;
counters = alloc_counters(table);
if (IS_ERR(counters))
@@ -961,6 +990,14 @@ copy_entries_to_user(unsigned int total_
ret = -EFAULT;
goto free_counters;
}
+
+ flags = e->ip.flags & IPT_F_MASK;
+ if (copy_to_user(userptr + off
+ + offsetof(struct ipt_entry, ip.flags),
+ &flags, sizeof(flags)) != 0) {
+ ret = -EFAULT;
+ goto free_counters;
+ }
for (i = sizeof(struct ipt_entry);
i < e->target_offset;

View File

@ -0,0 +1,81 @@
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -310,6 +310,33 @@ struct ipt_entry *ipt_next_entry(const s
return (void *)entry + entry->next_offset;
}
+static bool
+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict)
+{
+ struct xt_entry_target *t;
+ struct xt_standard_target *st;
+
+ if (e->target_offset != sizeof(struct ipt_entry))
+ return false;
+
+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH))
+ return false;
+
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->target)
+ return false;
+
+ st = (struct xt_standard_target *) t;
+ if (st->verdict == XT_RETURN)
+ return false;
+
+ if (st->verdict >= 0)
+ return false;
+
+ *verdict = (unsigned)(-st->verdict) - 1;
+ return true;
+}
+
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ipt_do_table(struct sk_buff *skb,
@@ -334,6 +361,25 @@ ipt_do_table(struct sk_buff *skb,
ip = ip_hdr(skb);
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
+
+ IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+ local_bh_disable();
+ addend = xt_write_recseq_begin();
+ private = table->private;
+ cpu = smp_processor_id();
+ table_base = private->entries[cpu];
+ jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
+ stackptr = per_cpu_ptr(private->stackptr, cpu);
+ origptr = *stackptr;
+
+ e = get_entry(table_base, private->hook_entry[hook]);
+ if (ipt_handle_default_rule(e, &verdict)) {
+ ADD_COUNTER(e->counters, skb->len, 1);
+ xt_write_recseq_end(addend);
+ local_bh_enable();
+ return verdict;
+ }
+
/* We handle fragments by dealing with the first fragment as
* if it was a normal packet. All other fragments are treated
* normally, except that they will NEVER match rules that ask
@@ -348,18 +394,6 @@ ipt_do_table(struct sk_buff *skb,
acpar.family = NFPROTO_IPV4;
acpar.hooknum = hook;
- IP_NF_ASSERT(table->valid_hooks & (1 << hook));
- local_bh_disable();
- addend = xt_write_recseq_begin();
- private = table->private;
- cpu = smp_processor_id();
- table_base = private->entries[cpu];
- jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
- stackptr = per_cpu_ptr(private->stackptr, cpu);
- origptr = *stackptr;
-
- e = get_entry(table_base, private->hook_entry[hook]);
-
pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
table->name, hook, origptr,
get_entry(table_base, private->underflow[hook]));

View File

@ -0,0 +1,16 @@
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -84,9 +84,11 @@ ip_packet_match(const struct iphdr *ip,
if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
return true;
- if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
+ if (FWINV(ipinfo->smsk.s_addr &&
+ (ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
IPT_INV_SRCIP) ||
- FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
+ FWINV(ipinfo->dmsk.s_addr &&
+ (ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
IPT_INV_DSTIP)) {
dprintf("Source or dest mismatch.\n");

View File

@ -0,0 +1,36 @@
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -29,6 +29,9 @@
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+/* Do not check the TCP window for incoming packets */
+static int nf_ct_tcp_no_window_check __read_mostly = 1;
+
/* "Be conservative in what you do,
be liberal in what you accept from others."
If it's non-zero, we mark only out of window RST segments as INVALID. */
@@ -524,6 +527,9 @@ static bool tcp_in_window(const struct n
s16 receiver_offset;
bool res;
+ if (nf_ct_tcp_no_window_check)
+ return true;
+
/*
* Get the required data from the packet.
*/
@@ -1321,6 +1327,13 @@ static struct ctl_table tcp_sysctl_table
.proc_handler = proc_dointvec,
},
{
+ .procname = "nf_conntrack_tcp_no_window_check",
+ .data = &nf_ct_tcp_no_window_check,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
.procname = "nf_conntrack_tcp_be_liberal",
.data = &nf_ct_tcp_be_liberal,
.maxlen = sizeof(unsigned int),

791
3.3.8/620-sched_esfq.patch Normal file
View File

@ -0,0 +1,791 @@
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -193,6 +193,33 @@ struct tc_sfq_xstats {
__s32 allot;
};
+/* ESFQ section */
+
+enum
+{
+ /* traditional */
+ TCA_SFQ_HASH_CLASSIC,
+ TCA_SFQ_HASH_DST,
+ TCA_SFQ_HASH_SRC,
+ TCA_SFQ_HASH_FWMARK,
+ /* conntrack */
+ TCA_SFQ_HASH_CTORIGDST,
+ TCA_SFQ_HASH_CTORIGSRC,
+ TCA_SFQ_HASH_CTREPLDST,
+ TCA_SFQ_HASH_CTREPLSRC,
+ TCA_SFQ_HASH_CTNATCHG,
+};
+
+struct tc_esfq_qopt
+{
+ unsigned quantum; /* Bytes per round allocated to flow */
+ int perturb_period; /* Period of hash perturbation */
+ __u32 limit; /* Maximal packets in queue */
+ unsigned divisor; /* Hash divisor */
+ unsigned flows; /* Maximal number of flows */
+ unsigned hash_kind; /* Hash function to use for flow identification */
+};
+
/* RED section */
enum {
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -148,6 +148,37 @@ config NET_SCH_SFQ
To compile this code as a module, choose M here: the
module will be called sch_sfq.
+config NET_SCH_ESFQ
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
+ ---help---
+ Say Y here if you want to use the Enhanced Stochastic Fairness
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
+ devices or as a leaf discipline for a classful qdisc such as HTB or
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
+ references to the SFQ algorithm).
+
+ This is an enchanced SFQ version which allows you to control some
+ hardcoded values in the SFQ scheduler.
+
+ ESFQ also adds control of the hash function used to identify packet
+ flows. The original SFQ discipline hashes by connection; ESFQ add
+ several other hashing methods, such as by src IP or by dst IP, which
+ can be more fair to users in some networking situations.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_esfq.
+
+config NET_SCH_ESFQ_NFCT
+ bool "Connection Tracking Hash Types"
+ depends on NET_SCH_ESFQ && NF_CONNTRACK
+ ---help---
+ Say Y here to enable support for hashing based on netfilter connection
+ tracking information. This is useful for a router that is also using
+ NAT to connect privately-addressed hosts to the Internet. If you want
+ to provide fair distribution of upstream bandwidth, ESFQ must use
+ connection tracking information, since all outgoing packets will share
+ the same source address.
+
config NET_SCH_TEQL
tristate "True Link Equalizer (TEQL)"
---help---
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_NET_SCH_INGRESS) += sch_ing
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
obj-$(CONFIG_NET_SCH_SFB) += sch_sfb.o
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
--- /dev/null
+++ b/net/sched/sch_esfq.c
@@ -0,0 +1,702 @@
+/*
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
+ * Added dynamic depth,limit,divisor,hash_kind options.
+ * Added dst and src hashes.
+ *
+ * Alexander Clouter, <alex@digriz.org.uk>
+ * Ported ESFQ to Linux 2.6.
+ *
+ * Corey Hickey, <bugfood-c@fatooh.org>
+ * Maintenance of the Linux 2.6 port.
+ * Added fwmark hash (thanks to Robert Kurjata).
+ * Added usage of jhash.
+ * Added conntrack support.
+ * Added ctnatchg hash (thanks to Ben Pfountz).
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/netlink.h>
+#include <linux/ipv6.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/jhash.h>
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+/* Stochastic Fairness Queuing algorithm.
+ For more comments look at sch_sfq.c.
+ The difference is that you can change limit, depth,
+ hash table size and choose alternate hash types.
+
+ classic: same as in sch_sfq.c
+ dst: destination IP address
+ src: source IP address
+ fwmark: netfilter mark value
+ ctorigdst: original destination IP address
+ ctorigsrc: original source IP address
+ ctrepldst: reply destination IP address
+ ctreplsrc: reply source IP
+
+*/
+
+#define ESFQ_HEAD 0
+#define ESFQ_TAIL 1
+
+/* This type should contain at least SFQ_DEPTH*2 values */
+typedef unsigned int esfq_index;
+
+struct esfq_head
+{
+ esfq_index next;
+ esfq_index prev;
+};
+
+struct esfq_sched_data
+{
+/* Parameters */
+ int perturb_period;
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
+ int limit;
+ unsigned depth;
+ unsigned hash_divisor;
+ unsigned hash_kind;
+/* Variables */
+ struct timer_list perturb_timer;
+ int perturbation;
+ esfq_index tail; /* Index of current slot in round */
+ esfq_index max_depth; /* Maximal depth */
+
+ esfq_index *ht; /* Hash table */
+ esfq_index *next; /* Active slots link */
+ short *allot; /* Current allotment per slot */
+ unsigned short *hash; /* Hash value indexed by slots */
+ struct sk_buff_head *qs; /* Slot queue */
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
+};
+
+/* This contains the info we will hash. */
+struct esfq_packet_info
+{
+ u32 proto; /* protocol or port */
+ u32 src; /* source from packet header */
+ u32 dst; /* destination from packet header */
+ u32 ctorigsrc; /* original source from conntrack */
+ u32 ctorigdst; /* original destination from conntrack */
+ u32 ctreplsrc; /* reply source from conntrack */
+ u32 ctrepldst; /* reply destination from conntrack */
+ u32 mark; /* netfilter mark (fwmark) */
+};
+
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
+{
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
+{
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
+{
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
+}
+
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
+{
+ struct esfq_packet_info info;
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+#endif
+
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
+ {
+ struct iphdr *iph = ip_hdr(skb);
+ info.dst = iph->daddr;
+ info.src = iph->saddr;
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
+ (iph->protocol == IPPROTO_TCP ||
+ iph->protocol == IPPROTO_UDP ||
+ iph->protocol == IPPROTO_SCTP ||
+ iph->protocol == IPPROTO_DCCP ||
+ iph->protocol == IPPROTO_ESP))
+ info.proto = *(((u32*)iph) + iph->ihl);
+ else
+ info.proto = iph->protocol;
+ break;
+ }
+ case __constant_htons(ETH_P_IPV6):
+ {
+ struct ipv6hdr *iph = ipv6_hdr(skb);
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
+ * but the code is simple. */
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
+ if (iph->nexthdr == IPPROTO_TCP ||
+ iph->nexthdr == IPPROTO_UDP ||
+ iph->nexthdr == IPPROTO_SCTP ||
+ iph->nexthdr == IPPROTO_DCCP ||
+ iph->nexthdr == IPPROTO_ESP)
+ info.proto = *(u32*)&iph[1];
+ else
+ info.proto = iph->nexthdr;
+ break;
+ }
+ default:
+ info.dst = (u32)(unsigned long)skb_dst(skb);
+ info.src = (u32)(unsigned long)skb->sk;
+ info.proto = skb->protocol;
+ }
+
+ info.mark = skb->mark;
+
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+ /* defaults if there is no conntrack info */
+ info.ctorigsrc = info.src;
+ info.ctorigdst = info.dst;
+ info.ctreplsrc = info.dst;
+ info.ctrepldst = info.src;
+ /* collect conntrack info */
+ if (ct && ct != &nf_conntrack_untracked) {
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
+ }
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ /* Again, hash ipv6 addresses into a single u32. */
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
+ }
+
+ }
+#endif
+
+ switch(q->hash_kind) {
+ case TCA_SFQ_HASH_CLASSIC:
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+ case TCA_SFQ_HASH_DST:
+ return esfq_jhash_1word(q, info.dst);
+ case TCA_SFQ_HASH_SRC:
+ return esfq_jhash_1word(q, info.src);
+ case TCA_SFQ_HASH_FWMARK:
+ return esfq_jhash_1word(q, info.mark);
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+ case TCA_SFQ_HASH_CTORIGDST:
+ return esfq_jhash_1word(q, info.ctorigdst);
+ case TCA_SFQ_HASH_CTORIGSRC:
+ return esfq_jhash_1word(q, info.ctorigsrc);
+ case TCA_SFQ_HASH_CTREPLDST:
+ return esfq_jhash_1word(q, info.ctrepldst);
+ case TCA_SFQ_HASH_CTREPLSRC:
+ return esfq_jhash_1word(q, info.ctreplsrc);
+ case TCA_SFQ_HASH_CTNATCHG:
+ {
+ if (info.ctorigdst == info.ctreplsrc)
+ return esfq_jhash_1word(q, info.ctorigsrc);
+ return esfq_jhash_1word(q, info.ctreplsrc);
+ }
+#endif
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
+ }
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+}
+
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d = q->qs[x].qlen + q->depth;
+
+ p = d;
+ n = q->dep[d].next;
+ q->dep[x].next = n;
+ q->dep[x].prev = p;
+ q->dep[p].next = q->dep[n].prev = x;
+}
+
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
+ q->max_depth--;
+
+ esfq_link(q, x);
+}
+
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+ d = q->qs[x].qlen;
+ if (q->max_depth < d)
+ q->max_depth = d;
+
+ esfq_link(q, x);
+}
+
+static unsigned int esfq_drop(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ esfq_index d = q->max_depth;
+ struct sk_buff *skb;
+ unsigned int len;
+
+ /* Queue is full! Find the longest slot and
+ drop a packet from it */
+
+ if (d > 1) {
+ esfq_index x = q->dep[d+q->depth].next;
+ skb = q->qs[x].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[x]);
+ kfree_skb(skb);
+ esfq_dec(q, x);
+ sch->q.qlen--;
+ sch->qstats.drops++;
+ sch->qstats.backlog -= len;
+ return len;
+ }
+
+ if (d == 1) {
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
+ d = q->next[q->tail];
+ q->next[q->tail] = q->next[d];
+ q->allot[q->next[d]] += q->quantum;
+ skb = q->qs[d].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[d]);
+ kfree_skb(skb);
+ esfq_dec(q, d);
+ sch->q.qlen--;
+ q->ht[q->hash[d]] = q->depth;
+ sch->qstats.drops++;
+ sch->qstats.backlog -= len;
+ return len;
+ }
+
+ return 0;
+}
+
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
+{
+ unsigned hash = esfq_hash(q, skb);
+ unsigned depth = q->depth;
+ esfq_index x;
+
+ x = q->ht[hash];
+ if (x == depth) {
+ q->ht[hash] = x = q->dep[depth].next;
+ q->hash[x] = hash;
+ }
+
+ if (end == ESFQ_TAIL)
+ __skb_queue_tail(&q->qs[x], skb);
+ else
+ __skb_queue_head(&q->qs[x], skb);
+
+ esfq_inc(q, x);
+ if (q->qs[x].qlen == 1) { /* The flow is new */
+ if (q->tail == depth) { /* It is the first flow */
+ q->tail = x;
+ q->next[x] = x;
+ q->allot[x] = q->quantum;
+ } else {
+ q->next[x] = q->next[q->tail];
+ q->next[q->tail] = x;
+ q->tail = x;
+ }
+ }
+}
+
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
+ sch->qstats.backlog += skb->len;
+ if (++sch->q.qlen < q->limit-1) {
+ sch->bstats.bytes += skb->len;
+ sch->bstats.packets++;
+ return 0;
+ }
+
+ sch->qstats.drops++;
+ esfq_drop(sch);
+ return NET_XMIT_CN;
+}
+
+static struct sk_buff *esfq_peek(struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ esfq_index a;
+
+ /* No active slots */
+ if (q->tail == q->depth)
+ return NULL;
+
+ a = q->next[q->tail];
+ return skb_peek(&q->qs[a]);
+}
+
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
+{
+ struct sk_buff *skb;
+ unsigned depth = q->depth;
+ esfq_index a, old_a;
+
+ /* No active slots */
+ if (q->tail == depth)
+ return NULL;
+
+ a = old_a = q->next[q->tail];
+
+ /* Grab packet */
+ skb = __skb_dequeue(&q->qs[a]);
+ esfq_dec(q, a);
+
+ /* Is the slot empty? */
+ if (q->qs[a].qlen == 0) {
+ q->ht[q->hash[a]] = depth;
+ a = q->next[a];
+ if (a == old_a) {
+ q->tail = depth;
+ return skb;
+ }
+ q->next[q->tail] = a;
+ q->allot[a] += q->quantum;
+ } else if ((q->allot[a] -= skb->len) <= 0) {
+ q->tail = a;
+ a = q->next[a];
+ q->allot[a] += q->quantum;
+ }
+
+ return skb;
+}
+
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+
+ skb = esfq_q_dequeue(q);
+ if (skb == NULL)
+ return NULL;
+ sch->q.qlen--;
+ sch->qstats.backlog -= skb->len;
+ return skb;
+}
+
+static void esfq_q_destroy(struct esfq_sched_data *q)
+{
+ del_timer(&q->perturb_timer);
+ if(q->ht)
+ kfree(q->ht);
+ if(q->dep)
+ kfree(q->dep);
+ if(q->next)
+ kfree(q->next);
+ if(q->allot)
+ kfree(q->allot);
+ if(q->hash)
+ kfree(q->hash);
+ if(q->qs)
+ kfree(q->qs);
+}
+
+static void esfq_destroy(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ esfq_q_destroy(q);
+}
+
+
+static void esfq_reset(struct Qdisc* sch)
+{
+ struct sk_buff *skb;
+
+ while ((skb = esfq_dequeue(sch)) != NULL)
+ kfree_skb(skb);
+}
+
+static void esfq_perturbation(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc*)arg;
+ struct esfq_sched_data *q = qdisc_priv(sch);
+
+ q->perturbation = net_random()&0x1F;
+
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+}
+
+static unsigned int esfq_check_hash(unsigned int kind)
+{
+ switch (kind) {
+ case TCA_SFQ_HASH_CTORIGDST:
+ case TCA_SFQ_HASH_CTORIGSRC:
+ case TCA_SFQ_HASH_CTREPLDST:
+ case TCA_SFQ_HASH_CTREPLSRC:
+ case TCA_SFQ_HASH_CTNATCHG:
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
+ {
+ if (net_ratelimit())
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
+ return TCA_SFQ_HASH_CLASSIC;
+ }
+#endif
+ case TCA_SFQ_HASH_CLASSIC:
+ case TCA_SFQ_HASH_DST:
+ case TCA_SFQ_HASH_SRC:
+ case TCA_SFQ_HASH_FWMARK:
+ return kind;
+ default:
+ {
+ if (net_ratelimit())
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
+ return TCA_SFQ_HASH_CLASSIC;
+ }
+ }
+}
+
+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
+{
+ struct tc_esfq_qopt *ctl = nla_data(opt);
+ esfq_index p = ~0U/2;
+ int i;
+
+ if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
+ return -EINVAL;
+
+ q->perturbation = 0;
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
+ q->max_depth = 0;
+ if (opt == NULL) {
+ q->perturb_period = 0;
+ q->hash_divisor = 1024;
+ q->tail = q->limit = q->depth = 128;
+
+ } else {
+ struct tc_esfq_qopt *ctl = nla_data(opt);
+ if (ctl->quantum)
+ q->quantum = ctl->quantum;
+ q->perturb_period = ctl->perturb_period*HZ;
+ q->hash_divisor = ctl->divisor ? : 1024;
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
+
+ if ( q->depth > p - 1 )
+ return -EINVAL;
+
+ if (ctl->limit)
+ q->limit = min_t(u32, ctl->limit, q->depth);
+
+ if (ctl->hash_kind) {
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
+ }
+ }
+
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->ht)
+ goto err_case;
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
+ if (!q->dep)
+ goto err_case;
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->next)
+ goto err_case;
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
+ if (!q->allot)
+ goto err_case;
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
+ if (!q->hash)
+ goto err_case;
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
+ if (!q->qs)
+ goto err_case;
+
+ for (i=0; i< q->hash_divisor; i++)
+ q->ht[i] = q->depth;
+ for (i=0; i<q->depth; i++) {
+ skb_queue_head_init(&q->qs[i]);
+ q->dep[i+q->depth].next = i+q->depth;
+ q->dep[i+q->depth].prev = i+q->depth;
+ }
+
+ for (i=0; i<q->depth; i++)
+ esfq_link(q, i);
+ return 0;
+err_case:
+ esfq_q_destroy(q);
+ return -ENOBUFS;
+}
+
+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ int err;
+
+ q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
+ if ((err = esfq_q_init(q, opt)))
+ return err;
+
+ init_timer(&q->perturb_timer);
+ q->perturb_timer.data = (unsigned long)sch;
+ q->perturb_timer.function = esfq_perturbation;
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+
+ return 0;
+}
+
+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ struct esfq_sched_data new;
+ struct sk_buff *skb;
+ int err;
+
+ /* set up new queue */
+ memset(&new, 0, sizeof(struct esfq_sched_data));
+ new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
+ if ((err = esfq_q_init(&new, opt)))
+ return err;
+
+ /* copy all packets from the old queue to the new queue */
+ sch_tree_lock(sch);
+ while ((skb = esfq_q_dequeue(q)) != NULL)
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
+
+ /* clean up the old queue */
+ esfq_q_destroy(q);
+
+ /* copy elements of the new queue into the old queue */
+ q->perturb_period = new.perturb_period;
+ q->quantum = new.quantum;
+ q->limit = new.limit;
+ q->depth = new.depth;
+ q->hash_divisor = new.hash_divisor;
+ q->hash_kind = new.hash_kind;
+ q->tail = new.tail;
+ q->max_depth = new.max_depth;
+ q->ht = new.ht;
+ q->dep = new.dep;
+ q->next = new.next;
+ q->allot = new.allot;
+ q->hash = new.hash;
+ q->qs = new.qs;
+
+ /* finish up */
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ } else {
+ q->perturbation = 0;
+ }
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct esfq_sched_data *q = qdisc_priv(sch);
+ unsigned char *b = skb_tail_pointer(skb);
+ struct tc_esfq_qopt opt;
+
+ opt.quantum = q->quantum;
+ opt.perturb_period = q->perturb_period/HZ;
+
+ opt.limit = q->limit;
+ opt.divisor = q->hash_divisor;
+ opt.flows = q->depth;
+ opt.hash_kind = q->hash_kind;
+
+ NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+ return skb->len;
+
+nla_put_failure:
+ nlmsg_trim(skb, b);
+ return -1;
+}
+
+static struct Qdisc_ops esfq_qdisc_ops =
+{
+ .next = NULL,
+ .cl_ops = NULL,
+ .id = "esfq",
+ .priv_size = sizeof(struct esfq_sched_data),
+ .enqueue = esfq_enqueue,
+ .dequeue = esfq_dequeue,
+ .peek = esfq_peek,
+ .drop = esfq_drop,
+ .init = esfq_init,
+ .reset = esfq_reset,
+ .destroy = esfq_destroy,
+ .change = esfq_change,
+ .dump = esfq_dump,
+ .owner = THIS_MODULE,
+};
+
+static int __init esfq_module_init(void)
+{
+ return register_qdisc(&esfq_qdisc_ops);
+}
+static void __exit esfq_module_exit(void)
+{
+ unregister_qdisc(&esfq_qdisc_ops);
+}
+module_init(esfq_module_init)
+module_exit(esfq_module_exit)
+MODULE_LICENSE("GPL");

Some files were not shown because too many files have changed in this diff Show More