Enscript Output

extractedLnx/linux-2.4.19/fs/intermezzo/psdev.c_presto_psdev_ioctl.c

static int presto_psdev_ioctl(struct inode *inode, struct file *file,
                              unsigned int cmd, unsigned long arg)
{
        struct upc_comm *upccom;
        /* XXX is this rdev or dev? */
        kdev_t dev = inode->i_rdev;

        ENTRY;
        upccom = presto_psdev_f2u(file);
        if ( !upccom) {
                printk("InterMezzo: %s, bad device %s\n",
                       __FUNCTION__, kdevname(dev));
                EXIT;
                return -ENODEV;
        }

        switch(cmd) {

        case TCGETS:
                return -EINVAL;

        case PRESTO_GETMOUNT: {
                /* return all the mounts for this device.  */
                int minor = 0;
                int len, outlen;
                struct readmount readmount;
                struct readmount *user_readmount = (struct readmount *) arg;
                char * tmp;
                int error = 0;

                if (copy_from_user(&readmount, (void *)arg, sizeof(readmount)))
                {
                        EXIT;
                        return -EFAULT;
                }

                len = readmount.io_len;
                minor = MINOR(dev);
                PRESTO_ALLOC(tmp, char *, len);
                if (!tmp) {
                        EXIT;
                        return -ENOMEM;
                }

                outlen = presto_sprint_mounts(tmp, len, minor);
                CDEBUG(D_PSDEV, "presto_sprint_mounts returns %d bytes\n",
                                outlen);

                /* as this came out on 1/3/2000, it could NEVER work.
                 * So fix it ... RGM
                 * I mean, let's let the compiler do a little work ...
                 * gcc suggested the extra ()
                 */
                if (copy_to_user(readmount.io_string, tmp, outlen)) {
                        CDEBUG(D_PSDEV, "Copy_to_user string 0x%p failed\n",
                               readmount.io_string);
			error = -EFAULT;
                }
                if (!error && copy_to_user(&(user_readmount->io_len),
                                           &outlen, sizeof(int))) {
                        CDEBUG(D_PSDEV, "Copy_to_user len @0x%p failed\n",
                               &(user_readmount->io_len));
			error = -EFAULT;
                }

                PRESTO_FREE(tmp, len);
                EXIT;
                return error;
        }

        case PRESTO_SETPID: {
                /*
                 * This ioctl is performed by each Lento that starts up
                 * and wants to do further communication with presto.
                 */
                CDEBUG(D_PSDEV, "Setting current pid to %d\n", current->pid);
                upccom->uc_pid = current->pid;
                if ( !list_empty(&upccom->uc_processing) ) {
                        struct list_head *lh;
                        struct upc_req *req;
                        printk("WARNING: setpid & processing not empty!\n");
                        lh = &upccom->uc_processing;
                        while ( (lh = lh->next) != &upccom->uc_processing) {
                                req = list_entry(lh, struct upc_req, rq_chain);
                                /* freeing of req and data is done by the sleeper */
                                wake_up(&req->rq_sleep);
                        }
                }
                if ( !list_empty(&upccom->uc_processing) ) {
                        printk("BAD: FAILDED TO CLEAN PROCESSING LIST!\n");
                }
                EXIT;
                return 0;
        }

        case PRESTO_CLEAR_FSETROOT: {
                /*
                 * Close KML files.
                 */
                int error;
                int saved_pid = upccom->uc_pid;
                char *path;
                struct {
                        char *path;
                        unsigned int path_len;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }
                
                if(input.path_len > PATH_MAX)
                {
                	EXIT;
                	return -EINVAL;
                }

                PRESTO_ALLOC(path, char *, input.path_len + 1);
                if ( !path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(path, input.path, input.path_len)) {
                        PRESTO_FREE(path, input.path_len + 1);
                        EXIT;
                        return -EFAULT;
                }
                path[input.path_len] = '\0';
                CDEBUG(D_PSDEV, "clear_fsetroot: path %s\n", path);

                upccom->uc_pid = current->pid;
                error = presto_clear_fsetroot(path);
                upccom->uc_pid = saved_pid;
                PRESTO_FREE(path, input.path_len + 1);
                EXIT;
                return error;
        }


        case PRESTO_CLEAR_ALL_FSETROOTS: {
                /*
                 * Close KML files.
                 */
                int error;
                int saved_pid = upccom->uc_pid;
                char *path;
                struct {
                        char *path;
                        unsigned int path_len;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }
                
                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                PRESTO_ALLOC(path, char *, input.path_len + 1);
                if ( !path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(path, input.path, input.path_len)) {
                        PRESTO_FREE(path, input.path_len + 1);
                        EXIT;
                        return -EFAULT;
                }
                path[input.path_len] = '\0';
                CDEBUG(D_PSDEV, "clear_all_fsetroot: path %s\n", path);

                upccom->uc_pid = current->pid;
                error = presto_clear_all_fsetroots(path);
                upccom->uc_pid = saved_pid;
                PRESTO_FREE(path, input.path_len + 1);
                EXIT;
                return error;
        }

        case PRESTO_GET_KMLSIZE: {
                int error;
                int saved_pid = upccom->uc_pid;
                char *path;
                size_t size = 0;
                struct {
                        __u64 size;
                        char *path;
                        unsigned int path_len;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                PRESTO_ALLOC(path, char *, input.path_len + 1);
                if ( !path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(path, input.path, input.path_len)) {
                        PRESTO_FREE(path, input.path_len + 1);
                        EXIT;
                        return -EFAULT;
                }
                path[input.path_len] = '\0';
                CDEBUG(D_PSDEV, "get_kmlsize: len %d path %s\n", 
                       input.path_len, path);

                upccom->uc_pid = current->pid;
                error = presto_get_kmlsize(path, &size);
                PRESTO_FREE(path, input.path_len + 1);
                if (error) {
                        EXIT;
                        return error;
                }
                input.size = size;
                upccom->uc_pid = saved_pid;

                CDEBUG(D_PSDEV, "get_kmlsize: size = %Zd\n", size);

                EXIT;
                if (copy_to_user((char *)arg, &input, sizeof(input)))
			return -EFAULT;
		return 0;
        }

        case PRESTO_GET_RECNO: {
                int error;
                int saved_pid = upccom->uc_pid;
                char *path;
                off_t recno = 0;
                struct {
                        __u64 recno;
                        char *path;
                        unsigned int path_len;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                PRESTO_ALLOC(path, char *, input.path_len + 1);
                if ( !path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(path, input.path, input.path_len)) {
                        PRESTO_FREE(path, input.path_len + 1);
                        EXIT;
                        return -EFAULT;
                }
                path[input.path_len] = '\0';
                CDEBUG(D_PSDEV, "get_recno: len %d path %s\n", 
                       input.path_len, path);

                upccom->uc_pid = current->pid;
                error = presto_get_lastrecno(path, &recno);
                PRESTO_FREE(path, input.path_len + 1);
                if (error) {
                        EXIT;
                        return error;
                }
                input.recno = recno;
                upccom->uc_pid = saved_pid;

                CDEBUG(D_PSDEV, "get_recno: recno = %d\n", (int) recno);

                EXIT;
                if (copy_to_user((char *)arg, &input, sizeof(input)))
			return -EFAULT;
		return 0;
        }

        case PRESTO_SET_FSETROOT: {
                /*
                 * Save information about the cache, and initialize "special"
                 * cache files (KML, etc).
                 */
                int error;
                int saved_pid = upccom->uc_pid;
                char *fsetname;
                char *path;
                struct {
                        char *path;
                        unsigned int path_len;
                        char *name;
                        unsigned int name_len;
                        int   id;
                        int   flags;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.name_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }
                
                PRESTO_ALLOC(path, char *, input.path_len + 1);
                if ( !path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(path, input.path, input.path_len)) {
                        EXIT;
			error = -EFAULT;
                        goto exit_free_path;
                }
                path[input.path_len] = '\0';

                PRESTO_ALLOC(fsetname, char *, input.name_len + 1);
                if ( !fsetname ) {
                        error = -ENOMEM;
                        EXIT;
                        goto exit_free_path;
                }
                if (copy_from_user(fsetname, input.name, input.name_len)) {
                        EXIT;
			error = -EFAULT;
                        goto exit_free_fsetname;
                }
                fsetname[input.name_len] = '\0';

                CDEBUG(D_PSDEV,
                       "set_fsetroot: path %s name %s, id %d, flags %x\n",
                       path, fsetname, input.id, input.flags);
                upccom->uc_pid = current->pid;
                error = presto_set_fsetroot(path, fsetname, input.id,input.flags);
                upccom->uc_pid = saved_pid;
                if ( error ) {
                        EXIT;
                        goto exit_free_fsetname;
                }
                /* fsetname is kept in the fset, so don't free it now */
                PRESTO_FREE(path, input.path_len + 1);
                EXIT;
                return 0;

        exit_free_fsetname:
                PRESTO_FREE(fsetname, input.name_len + 1);
        exit_free_path:
                PRESTO_FREE(path, input.path_len + 1);
                return error;
        }

        case PRESTO_CLOSE_JOURNALF: {
                int saved_pid = upccom->uc_pid;
                int error;

                CDEBUG(D_SUPER, "HELLO\n");

                /* pretend we are lento: we should lock something */
                upccom->uc_pid = current->pid;
                error = presto_close_journal_file(NULL);
                CDEBUG(D_PSDEV, "error is %d\n", error);
                upccom->uc_pid = saved_pid;
                EXIT;
                return error;
        }

        case PRESTO_GETOPT:
        case PRESTO_SETOPT: {
                /* return all the mounts for this device.  */
                int dosetopt(int, struct psdev_opt *);
                int dogetopt(int, struct psdev_opt *);
                int minor = 0;
                struct psdev_opt kopt;
                int error = 0;
                struct psdev_opt *user_opt = (struct psdev_opt *) arg;

                if (copy_from_user(&kopt, (void *)arg, sizeof(kopt))) {
                        printk("psdev: can't copyin %Zd bytes from %p to %p\n",
                               sizeof(kopt), (struct kopt *) arg, &kopt);
                        EXIT;
                        return -EFAULT;
                }
                minor = MINOR(dev);
                if (cmd == PRESTO_SETOPT)
                        error = dosetopt(minor, &kopt);

                if ( error ) {
                        CDEBUG(D_PSDEV,
                               "dosetopt failed minor %d, opt %d, val %d\n",
                               minor, kopt.optname, kopt.optval);
                        EXIT;
                        return error;
                }

                error = dogetopt(minor, &kopt);

                if ( error ) {
                        CDEBUG(D_PSDEV,
                               "dogetopt failed minor %d, opt %d, val %d\n",
                               minor, kopt.optname, kopt.optval);
                        EXIT;
                        return error;
                }

                if (copy_to_user(user_opt, &kopt, sizeof(kopt))) {
                        CDEBUG(D_PSDEV, "Copy_to_user opt 0x%p failed\n",
                               user_opt);
                        EXIT;
                        return -EFAULT;
                }
                CDEBUG(D_PSDEV, "dosetopt minor %d, opt %d, val %d return %d\n",
                         minor, kopt.optname, kopt.optval, error);
                EXIT;
                return 0;
        }

        case PRESTO_VFS_SETATTR: {
                int error;
                struct lento_input_attr input;
                struct iattr iattr;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }
                iattr.ia_valid = input.valid;
                iattr.ia_mode  = (umode_t)input.mode;
                iattr.ia_uid   = (uid_t)input.uid;
                iattr.ia_gid   = (gid_t)input.gid;
                iattr.ia_size  = (off_t)input.size;
                iattr.ia_atime = (time_t)input.atime;
                iattr.ia_mtime = (time_t)input.mtime;
                iattr.ia_ctime = (time_t)input.ctime;
                iattr.ia_attr_flags = input.attr_flags;

                error = lento_setattr(input.name, &iattr, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_CREATE: {
                int error;
                struct lento_input_mode input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_create(input.name, input.mode, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_LINK: {
                int error;
                struct lento_input_old_new input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_link(input.oldname, input.newname, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_UNLINK: {
                int error;
                struct lento_input input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_unlink(input.name, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_SYMLINK: {
                int error;
                struct lento_input_old_new input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_symlink(input.oldname, input.newname,&input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_MKDIR: {
                int error;
                struct lento_input_mode input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_mkdir(input.name, input.mode, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_RMDIR: {
                int error;
                struct lento_input input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_rmdir(input.name, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_MKNOD: {
                int error;
                struct lento_input_dev input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_mknod(input.name, input.mode,
                                    MKDEV(input.major,input.minor),&input.info);
                EXIT;
                return error;
        }

        case PRESTO_VFS_RENAME: {
                int error;
                struct lento_input_old_new input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                error = lento_rename(input.oldname, input.newname, &input.info);
                EXIT;
                return error;
        }

#ifdef CONFIG_FS_EXT_ATTR
        /* IOCTL to create/modify an extended attribute */
        case PRESTO_VFS_SETEXTATTR: {
                int error;
                struct lento_input_ext_attr input;
                char *name;
                char *buffer;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                    EXIT;
                    return -EFAULT;
                }

                /* Now setup the input parameters */
                PRESTO_ALLOC(name, char *, input.name_len+1);
                /* We need null terminated strings for attr names */
                name[input.name_len] = '\0';
                if (copy_from_user(name, input.name, input.name_len)) {
                    EXIT;
                    PRESTO_FREE(name,input.name_len+1);
                    return -EFAULT;
                }

                PRESTO_ALLOC(buffer, char *, input.buffer_len+1);
                if (copy_from_user(buffer, input.buffer, input.buffer_len)) {
                    EXIT;
                    PRESTO_FREE(name,input.name_len+1);
                    PRESTO_FREE(buffer,input.buffer_len+1);
                    return -EFAULT;
                }
                /* Make null terminated for easy printing */
                buffer[input.buffer_len]='\0';
 
                CDEBUG(D_PSDEV," setextattr params: name %s, valuelen %d,"
                       " value %s, attr flags %x, mode %o, slot offset %d,"
                       " recno %d, kml offset %lu, flags %x, time %d\n", 
                       name, input.buffer_len, buffer, input.flags, input.mode,
                       input.info.slot_offset, input.info.recno,
                       (unsigned long) input.info.kml_offset, input.info.flags,
                       input.info.updated_time);

                error=lento_set_ext_attr
                      (input.path,name,buffer,input.buffer_len,
                       input.flags, input.mode, &input.info);

                PRESTO_FREE(name,input.name_len+1);
                PRESTO_FREE(buffer,input.buffer_len+1);
                EXIT;
                return error;
        }

        /* IOCTL to delete an extended attribute */
        case PRESTO_VFS_DELEXTATTR: {
                int error;
                struct lento_input_ext_attr input;
                char *name;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                    EXIT;
                    return -EFAULT;
                }

                /* Now setup the input parameters */
                PRESTO_ALLOC(name, char *, input.name_len+1);
                /* We need null terminated strings for attr names */
                name[input.name_len] = '\0';
                if (copy_from_user(name, input.name, input.name_len)) {
                    EXIT;
                    PRESTO_FREE(name,input.name_len+1);
                    return -EFAULT;
                }

                CDEBUG(D_PSDEV," delextattr params: name %s,"
                       " attr flags %x, mode %o, slot offset %d, recno %d,"
                       " kml offset %lu, flags %x, time %d\n", 
                       name, input.flags, input.mode,
                       input.info.slot_offset, input.info.recno,
                       (unsigned long) input.info.kml_offset, input.info.flags,
                       input.info.updated_time);

                error=lento_set_ext_attr
                      (input.path,name,NULL,0,input.flags,
                       input.mode,&input.info);
                PRESTO_FREE(name,input.name_len+1);
                EXIT;
                return error;
        }
#endif

        case PRESTO_VFS_IOPEN: {
                struct lento_input_iopen input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                input.fd = lento_iopen(input.name, (ino_t)input.ino,
                                       input.generation, input.flags);
                CDEBUG(D_PIOCTL, "lento_iopen file descriptor: %d\n", input.fd);
                if (input.fd < 0) {
                        EXIT;
                        return input.fd;
                }
                EXIT;
                if (copy_to_user((char *)arg, &input, sizeof(input)))
			return -EFAULT;
		return 0;
        }

        case PRESTO_VFS_CLOSE: {
                int error;
                struct lento_input_close input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                CDEBUG(D_PIOCTL, "lento_close file descriptor: %d\n", input.fd);
                error = lento_close(input.fd, &input.info);
                EXIT;
                return error;
        }

        case PRESTO_BACKFETCH_LML: {
                char *user_path;
                struct lml_arg {
                        char *path;
                        __u32 path_len;
                        __u64 remote_ino;
                        __u32 remote_generation;
                        __u32 remote_version;
                        struct presto_version remote_file_version;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                user_path = input.path;

                PRESTO_ALLOC(input.path, char *, input.path_len + 1);
                if ( !input.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(input.path, user_path, input.path_len)) {
                        EXIT;
                        PRESTO_FREE(input.path, input.path_len + 1);
                        return -EFAULT;
                }
                input.path[input.path_len] = '\0';

                CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
                
                return lento_write_lml(input.path, 
                                       input.remote_ino, 
                                       input.remote_generation,
                                       input.remote_version,
                                       &input.remote_file_version); 

        }
                

        case PRESTO_CANCEL_LML: {
                char *user_path;
                struct lml_arg {
                        char *path;
                        __u64 lml_offset; 
                        __u32 path_len;
                        __u64 remote_ino;
                        __u32 remote_generation;
                        __u32 remote_version;
                        struct lento_vfs_context info;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                user_path = input.path;

                PRESTO_ALLOC(input.path, char *, input.path_len + 1);
                if ( !input.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(input.path, user_path, input.path_len)) {
                        EXIT;
                        PRESTO_FREE(input.path, input.path_len + 1);
                        return -EFAULT;
                }
                input.path[input.path_len] = '\0';

                CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
                
                return lento_cancel_lml(input.path, 
                                        input.lml_offset, 
                                        input.remote_ino, 
                                        input.remote_generation,
                                        input.remote_version,
                                        &input.info); 

        }

        case PRESTO_COMPLETE_CLOSES: {
                char *user_path;
                int error;
                struct lml_arg {
                        char *path;
                        __u32 path_len;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                user_path = input.path;

                PRESTO_ALLOC(input.path, char *, input.path_len + 1);
                if ( !input.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(input.path, user_path, input.path_len)) {
                        EXIT;
                        PRESTO_FREE(input.path, input.path_len + 1);
                        return -EFAULT;
                }
                input.path[input.path_len] = '\0';

                CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
                
                error = lento_complete_closes(input.path);
                PRESTO_FREE(input.path, input.path_len + 1);
                return error;
        }

        case PRESTO_RESET_FSET: {
                char *user_path;
                struct lml_arg {
                        char *path;
                        __u32 path_len;
                        __u64 offset;
                        __u32 recno;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                user_path = input.path;

                PRESTO_ALLOC(input.path, char *, input.path_len + 1);
                if ( !input.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(input.path, user_path, input.path_len)) {
                        EXIT;
                        PRESTO_FREE(input.path, input.path_len + 1);
                        return -EFAULT;
                }
                input.path[input.path_len] = '\0';

                CDEBUG(D_DOWNCALL, "lml name: %s\n", input.path);
                
                return lento_reset_fset(input.path, input.offset, input.recno); 

        }
                

        case PRESTO_MARK: {
                char *user_path;
                int res = 0;  /* resulting flags - returned to user */
                int error;
                struct {
                        int  mark_what;
                        int  and_flag;
                        int  or_flag;
                        unsigned int path_len;
                        char *path;
                } input;

                if (copy_from_user(&input, (char *)arg, sizeof(input))) {
                        EXIT;
                        return -EFAULT;
                }

                if(input.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }

                user_path = input.path;

                PRESTO_ALLOC(input.path, char *, input.path_len + 1);
                if ( !input.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(input.path, user_path, input.path_len)) {
                        EXIT;
                        PRESTO_FREE(input.path, input.path_len + 1);
                        return -EFAULT;
                }
                input.path[input.path_len] = '\0';

                CDEBUG(D_DOWNCALL, "mark name: %s, and: %x, or: %x, what %d\n",
                       input.path, input.and_flag, input.or_flag, 
                       input.mark_what);

                switch (input.mark_what) {
                case MARK_DENTRY:               
                        error = presto_mark_dentry(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &res);
                        break;
                case MARK_FSET:
                        error = presto_mark_fset(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &res);
                        break;
                case MARK_CACHE:
                        error = presto_mark_cache(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &res);
                        break;
                case MARK_GETFL: {
                        int fflags, cflags;
                        input.and_flag = 0xffffffff;
                        input.or_flag = 0; 
                        error = presto_mark_dentry(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &res);
                        if (error) 
                                break;
                        error = presto_mark_fset(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &fflags);
                        if (error) 
                                break;
                        error = presto_mark_cache(input.path,
                                                   input.and_flag,
                                                   input.or_flag, &cflags);

                        if (error) 
                                break;
                        input.and_flag = fflags;
                        input.or_flag = cflags;
                	break;
                }
                default:
                        error = -EINVAL;
                }

                PRESTO_FREE(input.path, input.path_len + 1);
                if (error == -EBUSY) {
                        input.and_flag = error;
                        error = 0;
                }
                if (error) { 
                        EXIT;
                        return error;
                }
                /* return the correct cookie to wait for */
                input.mark_what = res;
                if (copy_to_user((char *)arg, &input, sizeof(input)))
			return -EFAULT;
		return 0;
        }

#ifdef  CONFIG_KREINT
        case PRESTO_REINT_BEGIN:
                return begin_kml_reint (file, arg);
        case PRESTO_DO_REINT:
                return do_kml_reint (file, arg);
        case PRESTO_REINT_END:
                return end_kml_reint (file, arg);
#endif

        case PRESTO_RELEASE_PERMIT: {
                int error;
                char *user_path;
                struct {
                        int  cookie;
                        unsigned int path_len;
                        char *path;
                } permit;
                
                if (copy_from_user(&permit, (char *)arg, sizeof(permit))) {
                        EXIT;
                        return -EFAULT;
		}

                if(permit.path_len > PATH_MAX) {
                	EXIT;
                	return -EINVAL;
                }
                user_path = permit.path;
                
                PRESTO_ALLOC(permit.path, char *, permit.path_len + 1);
                if ( !permit.path ) {
                        EXIT;
                        return -ENOMEM;
                }
                if (copy_from_user(permit.path, user_path, permit.path_len)) {
                        EXIT;
                        PRESTO_FREE(permit.path, permit.path_len + 1);
                        return -EFAULT;
                }
                permit.path[permit.path_len] = '\0';
                
                CDEBUG(D_DOWNCALL, "release permit: %s, in cookie=%d\n",
                       permit.path, permit.cookie);
                error = presto_permit_downcall(permit.path, &permit.cookie);
                
                PRESTO_FREE(permit.path, permit.path_len + 1);
                if (error) {
                        EXIT;
                        return error;
                }
                /* return the correct cookie to wait for */
                if (copy_to_user((char *)arg, &permit, sizeof(permit)))
			return -EFAULT;
		return 0;
        }
        
        default:
                CDEBUG(D_PSDEV, "bad ioctl 0x%x, \n", cmd);
                CDEBUG(D_PSDEV, "valid are 0x%Zx - 0x%Zx, 0x%Zx - 0x%Zx \n",
                        PRESTO_GETMOUNT, PRESTO_GET_KMLSIZE,
                        PRESTO_VFS_SETATTR, PRESTO_VFS_IOPEN);
                EXIT;
        }

        return -EINVAL;
}

Generated by GNU enscript 1.6.4.