|
@@ -1313,6 +1313,21 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
|
|
|
v.val = sk->sk_incoming_cpu;
|
|
|
break;
|
|
|
|
|
|
+ case SO_MEMINFO:
|
|
|
+ {
|
|
|
+ u32 meminfo[SK_MEMINFO_VARS];
|
|
|
+
|
|
|
+ if (get_user(len, optlen))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ sk_get_meminfo(sk, meminfo);
|
|
|
+
|
|
|
+ len = min_t(unsigned int, len, sizeof(meminfo));
|
|
|
+ if (copy_to_user(optval, &meminfo, len))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ goto lenout;
|
|
|
+ }
|
|
|
default:
|
|
|
/* We implement the SO_SNDLOWAT etc to not be settable
|
|
|
* (1003.1g 7).
|
|
@@ -2861,6 +2876,21 @@ void sk_common_release(struct sock *sk)
|
|
|
}
|
|
|
EXPORT_SYMBOL(sk_common_release);
|
|
|
|
|
|
+void sk_get_meminfo(const struct sock *sk, u32 *mem)
|
|
|
+{
|
|
|
+ memset(mem, 0, sizeof(*mem) * SK_MEMINFO_VARS);
|
|
|
+
|
|
|
+ mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk);
|
|
|
+ mem[SK_MEMINFO_RCVBUF] = sk->sk_rcvbuf;
|
|
|
+ mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk);
|
|
|
+ mem[SK_MEMINFO_SNDBUF] = sk->sk_sndbuf;
|
|
|
+ mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc;
|
|
|
+ mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued;
|
|
|
+ mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc);
|
|
|
+ mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len;
|
|
|
+ mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops);
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
#define PROTO_INUSE_NR 64 /* should be enough for the first time */
|
|
|
struct prot_inuse {
|