Bug #51597 Using mlock ulimits for SHM_HUGETLB deprecated
Submitted: 1 Mar 2010 5:56 Modified: 14 Jan 2013 20:01
Reporter: wenk Luis Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:5.1.44 OS:Linux (gentoo 64bits)
Assigned to: Matthew Lord CPU Architecture:Any
Tags: Using mlock ulimits for SHM_HUGETLB deprecated

[1 Mar 2010 5:56] wenk Luis
Description:
dmesg WARNING:
------------[ cut here ]------------
WARNING: at fs/hugetlbfs/inode.c:954 hugetlb_file_setup+0x96/0x1ed()
Hardware name: .
Using mlock ulimits for SHM_HUGETLB deprecated
Modules linked in: w83627ehf hwmon_vid xfs k8temp rtc_cmos fan processor i2c_piix4 thermal hwmon button
Pid: 5598, comm: mysqld Not tainted 2.6.30-gentoo-r5 #2
Call Trace:
 [<ffffffff80310b61>] ? hugetlb_file_setup+0x96/0x1ed
 [<ffffffff80310b61>] ? hugetlb_file_setup+0x96/0x1ed
 [<ffffffff8023351d>] ? warn_slowpath_common+0x77/0xa3
 [<ffffffff802335a5>] ? warn_slowpath_fmt+0x51/0x59
 [<ffffffff8035f6f0>] ? sprintf+0x51/0x59
 [<ffffffff80343dd3>] ? ipc_rcu_alloc+0x4d/0x54
 [<ffffffff8028bda3>] ? user_shm_lock+0x35/0x75
 [<ffffffff80310b61>] ? hugetlb_file_setup+0x96/0x1ed
 [<ffffffff80347271>] ? newseg+0xd6/0x1e4
 [<ffffffff80343bdc>] ? ipcget+0x66/0x1a0
 [<ffffffff80347194>] ? sys_shmget+0x55/0x5c
 [<ffffffff8034719b>] ? newseg+0x0/0x1e4
 [<ffffffff803464d9>] ? shm_security+0x0/0x3
 [<ffffffff803464dc>] ? shm_more_checks+0x0/0xe
 [<ffffffff8020ae2b>] ? system_call_fastpath+0x16/0x1b
---[ end trace cc323d852697698e ]---

How to repeat:
enable large-pages=true in my.cnf
linux kernel 2.6.30-gentoo-r5
[2 Aug 2010 12:33] MySQL Verification Team
on my system, openSUSE 10.2 (X86-64), Linux box2 2.6.18.2-34-default.
nothing in /var/log/messages and dmesg but innodb said:

InnoDB: HugeTLB: Warning: Failed to allocate 419446784 bytes. errno 12
InnoDB HugeTLB: Warning: Using conventional memory pool
[2 Aug 2010 12:33] Susanne Ebrecht
I am not able to repeat this exactly on Ubuntu.

But I get the following message on start up:

100802 14:31:05 [Note] Plugin 'ndbcluster' is disabled.
InnoDB: HugeTLB: Warning: Failed to allocate 8404992 bytes. errno 1
InnoDB HugeTLB: Warning: Using conventional memory pool
[14 Jan 2013 20:01] Matthew Lord
The MySQL error log messages are simply the result of not having done the additional work outside of MySQL in order to get large pages working properly. For example:
  http://www.cyberciti.biz/tips/linux-hugetlbfs-and-mysql-performance.html
  http://time.to.pullthepl.ug/blog/2008/11/18/MySQL-Large-Pages-errors/

It is true that there is a potential to use the deprecated feature (fs/hugetlbfs/inode.c):
935 struct file *hugetlb_file_setup(const char *name, unsigned long addr,
936                                 size_t size, vm_flags_t acctflag,
937                                 struct user_struct **user, int creat_flags)
938 {
939         int error = -ENOMEM;
940         struct file *file;
941         struct inode *inode;
942         struct path path;
943         struct dentry *root;
944         struct qstr quick_string;
945         struct hstate *hstate;
946         unsigned long num_pages;
947 
948         *user = NULL;
949         if (!hugetlbfs_vfsmount)
950                 return ERR_PTR(-ENOENT);
951 
952         if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
953                 *user = current_user();
954                 if (user_shm_lock(size, *user)) {
955                         task_lock(current);
956                         printk_once(KERN_WARNING
957                                 "%s (%d): Using mlock ulimits for SHM_HUGETLB is deprecated\n",
958                                 current->comm, current->pid);
959                         task_unlock(current);
960                 } else {
961                         *user = NULL;
962                         return ERR_PTR(-EPERM);
963                 }
964         }

However I am not able to repeat the issue using MySQL 5.5.29 on Ubuntu 12.10 x86_64. I get no kernel log message about this being used, and there is nowhere within MySQL that we make the hugetlb_file_setup call. The deprecated feature is used and the log message triggered when:
  creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()

All we are doing is calling shmget, shmat, and shmctl:
  http://linux.die.net/man/2/shmget
  http://linux.die.net/man/2/shmat
  http://linux.die.net/man/2/shmctl

From "mysys/my_largepage.c":
uchar* my_large_malloc_int(size_t size, myf my_flags)
{
  int shmid;
  uchar* ptr;
  struct shmid_ds buf;
  DBUG_ENTER("my_large_malloc_int");

  /* Align block size to my_large_page_size */
  size= MY_ALIGN(size, (size_t) my_large_page_size);

  shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W);
  if (shmid < 0)
  {
    if (my_flags & MY_WME)
      fprintf(stderr,
              "Warning: Failed to allocate %lu bytes from HugeTLB memory."
              " errno %d\n", (ulong) size, errno);

    DBUG_RETURN(NULL);
  }

  ptr = (uchar*) shmat(shmid, NULL, 0);
  if (ptr == (uchar *) -1)
  {
    if (my_flags& MY_WME)
      fprintf(stderr, "Warning: Failed to attach shared memory segment,"
              " errno %d\n", errno);
    shmctl(shmid, IPC_RMID, &buf);

    DBUG_RETURN(NULL);
  }

  /*
    Remove the shared memory segment so that it will be automatically freed
    after memory is detached or process exits
  */
  shmctl(shmid, IPC_RMID, &buf);

  DBUG_RETURN(ptr);
}

I don't see where we're ever directly modifying, setting, or specifying anything related to either conditional:
  creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()

It seems that this is something handled by the local kernel and its large pages implementation. Perhaps it's related to whether you use /proc/sys/vm/hugetlb_shm_group as the can_do_hugetlb_shm() call does this (from fs/hugetlbfs/inode.c):
928 static int can_do_hugetlb_shm(void)
929 {
930         kgid_t shm_group;
931         shm_group = make_kgid(&init_user_ns, sysctl_hugetlb_shm_group);
932         return capable(CAP_IPC_LOCK) || in_group_p(shm_group);
933 }

Please correct me if I'm wrong. For now at least, I will mark this as can't repeat. It seems that this is all done outside of MySQL and in the general large pages setup on the system. I don't see any clear documentation on setting up large pages WITHOUT using  /proc/sys/vm/hugetlb_shm_group.