This shouldn't be too controversial. I simply looked for where there was a tiny bit of waste in the message queue code. Signed-off-by: Steven Stewart-Gallus <sstewartgallus00@xxxxxxxxxxxxxxx> --- diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 4fcf39a..aa3f903 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -278,16 +278,29 @@ static struct inode *mqueue_get_inode(struct super_block *sb, mq_bytes = mq_treesize + (info->attr.mq_maxmsg * info->attr.mq_msgsize); - spin_lock(&mq_lock); - if (u->mq_bytes + mq_bytes < u->mq_bytes || - u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) { + { + bool too_many_open_files; + long msgqueue_lim; + unsigned long u_bytes; + + msgqueue_lim = rlimit(RLIMIT_MSGQUEUE); + + spin_lock(&mq_lock); + + u_bytes = u->mq_bytes; + too_many_open_files = u_bytes + mq_bytes < u_bytes || + u_bytes + mq_bytes > msgqueue_lim; + if (!too_many_open_files) + u->mq_bytes += mq_bytes; + spin_unlock(&mq_lock); + /* mqueue_evict_inode() releases info->messages */ - ret = -EMFILE; - goto out_inode; + if (too_many_open_files) { + ret = -EMFILE; + goto out_inode; + } } - u->mq_bytes += mq_bytes; - spin_unlock(&mq_lock); /* all is ok */ info->user = get_uid(u); @@ -423,44 +436,60 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { struct inode *inode; - struct mq_attr *attr = dentry->d_fsdata; - int error; + struct mq_attr *attr; struct ipc_namespace *ipc_ns; + int error = 0; + + if (!capable(CAP_SYS_RESOURCE)) { + error = -ENOSPC; + goto finish; + } + + attr = dentry->d_fsdata; spin_lock(&mq_lock); ipc_ns = __get_ns_from_inode(dir); if (!ipc_ns) { error = -EACCES; - goto out_unlock; + goto unlock_mq; } - if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max && - !capable(CAP_SYS_RESOURCE)) { + if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max) { error = -ENOSPC; - goto out_unlock; + goto unlock_mq; } ipc_ns->mq_queues_count++; +unlock_mq: spin_unlock(&mq_lock); + if (error != 0) + goto put_ipc_ns; + inode = mqueue_get_inode(dir->i_sb, ipc_ns, mode, attr); if (IS_ERR(inode)) { error = PTR_ERR(inode); + spin_lock(&mq_lock); ipc_ns->mq_queues_count--; - goto out_unlock; + spin_unlock(&mq_lock); + + goto put_ipc_ns; } - put_ipc_ns(ipc_ns); +put_ipc_ns: + if (ipc_ns) + put_ipc_ns(ipc_ns); + + if (error != 0) + goto finish; + dir->i_size += DIRENT_SIZE; dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME; d_instantiate(dentry, inode); dget(dentry); - return 0; -out_unlock: - spin_unlock(&mq_lock); - if (ipc_ns) - put_ipc_ns(ipc_ns); + +finish: return error; } @@ -485,26 +514,39 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry) static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, size_t count, loff_t *off) { - struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp)); - char buffer[FILENT_SIZE]; ssize_t ret; + pid_t notify_owner; + unsigned long qsize; + struct sigevent notify; - spin_lock(&info->lock); - snprintf(buffer, sizeof(buffer), - "QSIZE:%-10lu NOTIFY:%-5d SIGNO:%-5d NOTIFY_PID:%-6d\n", - info->qsize, - info->notify_owner ? info->notify.sigev_notify : 0, - (info->notify_owner && - info->notify.sigev_notify == SIGEV_SIGNAL) ? - info->notify.sigev_signo : 0, - pid_vnr(info->notify_owner)); - spin_unlock(&info->lock); - buffer[sizeof(buffer)-1] = '\0'; + { + struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp)); - ret = simple_read_from_buffer(u_data, count, off, buffer, - strlen(buffer)); - if (ret <= 0) - return ret; + spin_lock(&info->lock); + notify_owner = pid_vnr(info->notify_owner); + notify = info->notify; + qsize = info->qsize; + spin_unlock(&info->lock); + } + + { + char buffer[FILENT_SIZE]; + + snprintf(buffer, sizeof(buffer), + "QSIZE:%-10lu NOTIFY:%-5d SIGNO:%-5d NOTIFY_PID:%-6d\n", + qsize, + notify_owner ? notify.sigev_notify : 0, + (notify_owner && + notify.sigev_notify == SIGEV_SIGNAL) ? + notify.sigev_signo : 0, + notify_owner); + buffer[sizeof(buffer)-1] = '\0'; + + ret = simple_read_from_buffer(u_data, count, off, buffer, + strlen(buffer)); + if (ret <= 0) + return ret; + } file_inode(filp)->i_atime = file_inode(filp)->i_ctime = CURRENT_TIME; return ret; @@ -524,18 +566,26 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id) static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab) { - struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp)); int retval = 0; + unsigned long curmsgs; + unsigned long maxmsg; - poll_wait(filp, &info->wait_q, poll_tab); + { + struct mqueue_inode_info *info = MQUEUE_I(file_inode(filp)); - spin_lock(&info->lock); - if (info->attr.mq_curmsgs) + poll_wait(filp, &info->wait_q, poll_tab); + + spin_lock(&info->lock); + curmsgs = info->attr.mq_curmsgs; + maxmsg = info->attr.mq_maxmsg; + spin_unlock(&info->lock); + } + + if (curmsgs) retval = POLLIN | POLLRDNORM; - if (info->attr.mq_curmsgs < info->attr.mq_maxmsg) + if (curmsgs < maxmsg) retval |= POLLOUT | POLLWRNORM; - spin_unlock(&info->lock); return retval; } -- To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.linux-learn.org/faqs