/* * This is the system call interface. This communicates with * the user-level programs. Currently this only supports diskquota * calls. Maybe we need to add the process quotas etc. in the future, * but we probably should use rlimits for that. */ asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr) { uint cmds, type; struct super_block *sb = NULL; int ret = -EINVAL; lock_kernel(); cmds = cmd >> SUBCMDSHIFT; type = cmd & SUBCMDMASK; #ifdef CONFIG_QIFACE_COMPAT if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) { ret = PTR_ERR(sb); sb = NULL; goto out; } if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) { if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0) goto out; ret = do_compat_quotactl(sb, type, cmds, id, addr); goto out; } #else if (IS_ERR(sb = resolve_dev(special))) { ret = PTR_ERR(sb); sb = NULL; goto out; } #endif if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0) goto out; ret = do_quotactl(sb, type, cmds, id, addr); out: if (sb) drop_super(sb); unlock_kernel(); return ret; }
static int ctrl_handle_add_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm; unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr); /* TODO - flags, etc */ unsigned int i, index = 0; int err = 0; LOG_DBG("adding %u services, msg size %u\n", num_res, CTRLMSG_SERVICE_LEN(cmr)); for (i = 0; i < num_res; i++) { struct net_device *dev = NULL; struct service_info *entry = &cmr->service[i]; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; if (entry->type == SERVICE_RULE_FORWARD) { dev = resolve_dev(entry); if (!dev) continue; } if (entry->srvid_prefix_bits > 0) prefix_bits = entry->srvid_prefix_bits; #if defined(ENABLE_DEBUG) { char ipstr[18]; LOG_DBG("Adding service id: %s(%u) " "@ address %s, priority %u, weight %u\n", service_id_to_str(&entry->srvid), prefix_bits, inet_ntop(AF_INET, &entry->address, ipstr, sizeof(ipstr)), entry->priority, entry->weight); } #endif err = service_add(&entry->srvid, prefix_bits, entry->type, entry->srvid_flags, entry->priority, entry->weight, &entry->address, sizeof(entry->address), make_target(dev), GFP_KERNEL); if (dev) dev_put(dev); if (err > 0) { if (index < i) { /* copy it over */ memcpy(&cmr->service[index], entry, sizeof(*entry)); } index++; } else { LOG_ERR("Error adding service %s: err=%d\n", service_id_to_str(&entry->srvid), err); } } if (index == 0) { /* Just return the original request with a return value */ cm->retval = CTRLMSG_RETVAL_NOENTRY; } else { /* Return the entries added */ cm->retval = CTRLMSG_RETVAL_OK; cm->len = CTRLMSG_SERVICE_NUM_LEN(index); } ctrl_sendmsg(cm, peer, GFP_KERNEL); return 0; }
static int ctrl_handle_mod_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm; unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr); unsigned int i, index = 0; int err = 0; if (num_res < 2 || num_res % 2 != 0) { LOG_DBG("Not an even number of service infos\n"); return 0; } LOG_DBG("modifying %u services\n", num_res / 2); for (i = 0; i < num_res; i += 2) { struct net_device *dev; struct service_info *entry_old = &cmr->service[i]; struct service_info *entry_new = &cmr->service[i+1]; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; if (entry_old->srvid_prefix_bits > 0) prefix_bits = entry_old->srvid_prefix_bits; #if defined(ENABLE_DEBUG) { char buf[18]; LOG_DBG("Modifying: %s flags(%i) bits(%i) %s\n", service_id_to_str(&entry_old->srvid), entry_old->srvid_flags, prefix_bits, inet_ntop(AF_INET, &entry_old->address, buf, 18)); } #endif dev = resolve_dev(entry_old); if (!dev) continue; err = service_modify(&entry_old->srvid, prefix_bits, SERVICE_RULE_FORWARD, entry_old->srvid_flags, entry_new->priority, entry_new->weight, &entry_old->address, sizeof(entry_old->address), &entry_new->address, sizeof(entry_new->address), make_target(dev)); if (err > 0) { if (index < i) { /* copy it over */ memcpy(&cmr->service[index], entry_new, sizeof(*entry_new)); } index++; } else { LOG_ERR("Could not modify service %s: %i\n", service_id_to_str(&entry_old->srvid), err); } dev_put(dev); } if (index == 0) { cm->retval = CTRLMSG_RETVAL_NOENTRY; } else { cm->retval = CTRLMSG_RETVAL_OK; cm->len = CTRLMSG_SERVICE_NUM_LEN(index); } ctrl_sendmsg(cm, peer, GFP_KERNEL); return 0; }