CVSROOT: /cvs/cluster Module name: cluster Branch: RHEL51 Changes by: [EMAIL PROTECTED] 2008-01-24 21:25:41
Modified files: gfs-kernel/src/gfs: gfs_ioctl.h ioctl.c ioctl.h ops_file.c Log message: Resolves: bz 430154: gfs_tool doesn't recognize GFS file sytem Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/gfs_ioctl.h.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.11&r2=1.11.6.1 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.13.2.4&r2=1.13.2.4.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.h.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.3&r2=1.3.6.1 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_file.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.28.2.2&r2=1.28.2.2.2.1 --- cluster/gfs-kernel/src/gfs/gfs_ioctl.h 2006/07/10 23:22:34 1.11 +++ cluster/gfs-kernel/src/gfs/gfs_ioctl.h 2008/01/24 21:25:41 1.11.6.1 @@ -22,12 +22,23 @@ #define GFS_IOCTL_SUPER _GFSC_(45) struct gfs_ioctl { - unsigned int gi_argc; - char **gi_argv; + unsigned int gi_argc; + char **gi_argv; char __user *gi_data; + unsigned int gi_size; + uint64_t gi_offset; +}; + +#ifdef CONFIG_COMPAT +struct gfs_ioctl_compat { + unsigned int gi_argc; + uint32_t gi_argv; + + uint32_t gi_data; unsigned int gi_size; uint64_t gi_offset; }; +#endif #endif /* ___GFS_IOCTL_DOT_H__ */ --- cluster/gfs-kernel/src/gfs/ioctl.c 2007/06/19 14:47:07 1.13.2.4 +++ cluster/gfs-kernel/src/gfs/ioctl.c 2008/01/24 21:25:41 1.13.2.4.2.1 @@ -19,6 +19,7 @@ #include <linux/completion.h> #include <linux/buffer_head.h> #include <asm/uaccess.h> +#include <linux/compat.h> #include "gfs_ioctl.h" #include "gfs.h" @@ -509,7 +510,7 @@ */ static int -gi_set_tune(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_set_tune(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { struct gfs_tune *gt = &sdp->sd_tune; char param[ARG_SIZE], value[ARG_SIZE]; @@ -521,12 +522,21 @@ if (gi->gi_argc != 3) return -EINVAL; - if (strncpy_from_user(param, gi->gi_argv[1], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(param, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(param, gi->gi_argv[1], ARG_SIZE); + } param[ARG_SIZE - 1] = 0; - if (strncpy_from_user(value, gi->gi_argv[2], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(value, gi->gi_argv[2], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(value, gi->gi_argv[2], ARG_SIZE); + } + value[ARG_SIZE - 1] = 0; if (strcmp(param, "ilimit1") == 0) { @@ -884,7 +894,7 @@ */ static int -gi_set_file_flag(struct gfs_inode *ip, struct gfs_ioctl *gi) +gi_set_file_flag(struct gfs_inode *ip, struct gfs_ioctl *gi, int from_user) { char buf[ARG_SIZE]; int set; @@ -896,8 +906,12 @@ if (gi->gi_argc != 3) return -EINVAL; - if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } buf[ARG_SIZE - 1] = 0; if (strcmp(buf, "set") == 0) @@ -907,8 +921,12 @@ else return -EINVAL; - if (strncpy_from_user(buf, gi->gi_argv[2], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[2], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[2], ARG_SIZE); + } buf[ARG_SIZE - 1] = 0; error = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); @@ -1065,15 +1083,19 @@ */ static struct gfs_inode * -gi2hip(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi2hip(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { char buf[ARG_SIZE]; if (gi->gi_argc != 2) return ERR_PTR(-EINVAL); - if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) - return ERR_PTR(-EFAULT); + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return ERR_PTR(-EFAULT); + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } buf[ARG_SIZE - 1] = 0; if (strcmp(buf, "jindex") == 0) @@ -1097,14 +1119,14 @@ */ static int -gi_get_hfile_stat(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_get_hfile_stat(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { struct gfs_inode *ip; struct gfs_dinode *di; struct gfs_holder i_gh; int error; - ip = gi2hip(sdp, gi); + ip = gi2hip(sdp, gi, from_user); if (IS_ERR(ip)) return PTR_ERR(ip); @@ -1142,7 +1164,7 @@ */ static int -gi_do_hfile_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_do_hfile_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { struct gfs_inode *ip; struct gfs_holder i_gh; @@ -1151,7 +1173,7 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ip = gi2hip(sdp, gi); + ip = gi2hip(sdp, gi, from_user); if (IS_ERR(ip)) return PTR_ERR(ip); @@ -1179,7 +1201,7 @@ */ static int -gi_do_hfile_write(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_do_hfile_write(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { struct gfs_inode *ip; struct gfs_alloc *al = NULL; @@ -1191,7 +1213,7 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ip = gi2hip(sdp, gi); + ip = gi2hip(sdp, gi, from_user); if (IS_ERR(ip)) return PTR_ERR(ip); @@ -1248,8 +1270,12 @@ goto out_relse; } - error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, - gfs_copy_from_user, NULL); + if (from_user) + error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, + gfs_copy_from_user, NULL); + else + error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, + gfs_copy_from_mem, NULL); gfs_trans_end(sdp); @@ -1283,7 +1309,7 @@ */ static int -gi_do_hfile_trunc(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_do_hfile_trunc(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { struct gfs_inode *ip; struct gfs_holder i_gh; @@ -1292,7 +1318,7 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ip = gi2hip(sdp, gi); + ip = gi2hip(sdp, gi, from_user); if (IS_ERR(ip)) return PTR_ERR(ip); @@ -1335,7 +1361,7 @@ */ static int -gi_do_quota_refresh(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_do_quota_refresh(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { char buf[ARG_SIZE]; int user; @@ -1346,8 +1372,12 @@ if (gi->gi_argc != 2) return -EINVAL; - if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } buf[ARG_SIZE - 1] = 0; switch (buf[0]) { @@ -1379,7 +1409,7 @@ */ static int -gi_do_quota_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi) +gi_do_quota_read(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user) { char buf[ARG_SIZE]; int user; @@ -1392,8 +1422,12 @@ if (gi->gi_size != sizeof(struct gfs_quota)) return -EINVAL; - if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) - return -EFAULT; + if (from_user) { + if (strncpy_from_user(buf, gi->gi_argv[1], ARG_SIZE) < 0) + return -EFAULT; + } else { + strncpy(buf, gi->gi_argv[1], ARG_SIZE); + } buf[ARG_SIZE - 1] = 0; switch (buf[0]) { @@ -1423,8 +1457,64 @@ return 0; } +int +gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi, const char *arg0, + int from_user) +{ + int error = -EFAULT; + + if (strcmp(arg0, "get_cookie") == 0) + error = gi_skeleton(ip, gi, gi_get_cookie); + else if (strcmp(arg0, "get_super") == 0) + error = gi_get_super(ip->i_sbd, gi); + else if (strcmp(arg0, "get_args") == 0) + error = gi_skeleton(ip, gi, gi_get_args); + else if (strcmp(arg0, "get_lockstruct") == 0) + error = gi_skeleton(ip, gi, gi_get_lockstruct); + else if (strcmp(arg0, "get_stat_gfs") == 0) + error = gi_skeleton(ip, gi, gi_get_stat_gfs); + else if (strcmp(arg0, "get_counters") == 0) + error = gi_skeleton(ip, gi, gi_get_counters); + else if (strcmp(arg0, "get_tune") == 0) + error = gi_skeleton(ip, gi, gi_get_tune); + else if (strcmp(arg0, "set_tune") == 0) + error = gi_set_tune(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_reclaim") == 0) + error = gi_skeleton(ip, gi, gi_do_reclaim); + else if (strcmp(arg0, "do_shrink") == 0) + error = gi_do_shrink(ip->i_sbd, gi); + else if (strcmp(arg0, "get_file_stat") == 0) + error = gi_get_file_stat(ip, gi); + else if (strcmp(arg0, "set_file_flag") == 0) + error = gi_set_file_flag(ip, gi, from_user); + else if (strcmp(arg0, "get_file_meta") == 0) + error = gi_get_file_meta(ip, gi); + else if (strcmp(arg0, "get_file_meta_quota") == 0) + error = gi_get_file_meta(ip->i_sbd->sd_qinode, &gi); + else if (strcmp(arg0, "do_file_flush") == 0) + error = gi_do_file_flush(ip, gi); + else if (strcmp(arg0, "get_hfile_stat") == 0) + error = gi_get_hfile_stat(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_read") == 0) + error = gi_do_hfile_read(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_write") == 0) + error = gi_do_hfile_write(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_hfile_trunc") == 0) + error = gi_do_hfile_trunc(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_quota_sync") == 0) + error = gi_do_quota_sync(ip->i_sbd, gi); + else if (strcmp(arg0, "do_quota_refresh") == 0) + error = gi_do_quota_refresh(ip->i_sbd, gi, from_user); + else if (strcmp(arg0, "do_quota_read") == 0) + error = gi_do_quota_read(ip->i_sbd, gi, from_user); + else + error = -ENOTTY; + + return error; +} + /** - * gfs_ioctl_i - + * gfs_ioctl_i - Normal ioctls * @ip: * @arg: * @@ -1455,56 +1545,73 @@ if (strncpy_from_user(arg0, argv[0], ARG_SIZE) < 0) goto out; arg0[ARG_SIZE - 1] = 0; - - if (strcmp(arg0, "get_cookie") == 0) - error = gi_skeleton(ip, &gi, gi_get_cookie); - else if (strcmp(arg0, "get_super") == 0) - error = gi_get_super(ip->i_sbd, &gi); - else if (strcmp(arg0, "get_args") == 0) - error = gi_skeleton(ip, &gi, gi_get_args); - else if (strcmp(arg0, "get_lockstruct") == 0) - error = gi_skeleton(ip, &gi, gi_get_lockstruct); - else if (strcmp(arg0, "get_stat_gfs") == 0) - error = gi_skeleton(ip, &gi, gi_get_stat_gfs); - else if (strcmp(arg0, "get_counters") == 0) - error = gi_skeleton(ip, &gi, gi_get_counters); - else if (strcmp(arg0, "get_tune") == 0) - error = gi_skeleton(ip, &gi, gi_get_tune); - else if (strcmp(arg0, "set_tune") == 0) - error = gi_set_tune(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_reclaim") == 0) - error = gi_skeleton(ip, &gi, gi_do_reclaim); - else if (strcmp(arg0, "do_shrink") == 0) - error = gi_do_shrink(ip->i_sbd, &gi); - else if (strcmp(arg0, "get_file_stat") == 0) - error = gi_get_file_stat(ip, &gi); - else if (strcmp(arg0, "set_file_flag") == 0) - error = gi_set_file_flag(ip, &gi); - else if (strcmp(arg0, "get_file_meta") == 0) - error = gi_get_file_meta(ip, &gi); - else if (strcmp(arg0, "do_file_flush") == 0) - error = gi_do_file_flush(ip, &gi); - else if (strcmp(arg0, "get_hfile_stat") == 0) - error = gi_get_hfile_stat(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_hfile_read") == 0) - error = gi_do_hfile_read(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_hfile_write") == 0) - error = gi_do_hfile_write(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_hfile_trunc") == 0) - error = gi_do_hfile_trunc(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_quota_sync") == 0) - error = gi_do_quota_sync(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_quota_refresh") == 0) - error = gi_do_quota_refresh(ip->i_sbd, &gi); - else if (strcmp(arg0, "do_quota_read") == 0) - error = gi_do_quota_read(ip->i_sbd, &gi); - else - error = -ENOTTY; - + error = gfs_ioctl_i_local(ip, &gi, arg0, 1); out: kfree(argv); return error; } +#ifdef CONFIG_COMPAT +/** + * gfs_ioctl_i_compat - compatibility ioctls + * These ioctls are used to provide ioctls for situations + * where userland and kernel arch is different. + * For example, userland may be 32-bit ppc whereas the + * kernel may be ppc64. In this case, we need to do + * extra translation between the addresses. + * @ip: + * @arg: + * + * Returns: -errno or positive byte count + */ + +int +gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg) +{ + struct gfs_ioctl_compat *src; + struct gfs_ioctl dst; + char **argv, *argptr; + uint32_t *ptr; + char arg0[ARG_SIZE]; + char *tmparg; + int i; + int error = -EFAULT; + + src = (struct gfs_ioctl_compat *)compat_ptr(arg); + memset(&dst, 0, sizeof(dst)); + dst.gi_argc = src->gi_argc; + dst.gi_size = src->gi_size; + dst.gi_offset = src->gi_offset; + + argv = kmalloc(dst.gi_argc * sizeof(char *), GFP_KERNEL); + if (!argv) + return -ENOMEM; + + memset(argv, 0, dst.gi_argc * sizeof(char *)); + ptr = (uint32_t *)compat_ptr(src->gi_argv); + + for (i = 0; i < dst.gi_argc; i++) { /* for each parm */ + tmparg = kmalloc(ARG_SIZE * sizeof(char *), GFP_KERNEL); + if (!tmparg) + goto out; + argptr = (char *)compat_ptr(*ptr); + if (strncpy_from_user(tmparg, argptr, ARG_SIZE) < 0) + goto out; + argv[i] = tmparg; + ptr++; + } + + strncpy(arg0, argv[0], ARG_SIZE); + arg0[ARG_SIZE - 1] = 0; + dst.gi_argv = argv; + dst.gi_data = compat_ptr(src->gi_data); + error = gfs_ioctl_i_local(ip, &dst, arg0, 0); + out: + for (i = 0; i < dst.gi_argc; i++) + kfree(argv[i]); + kfree(argv); + return error; +} +#endif --- cluster/gfs-kernel/src/gfs/ioctl.h 2006/07/10 23:22:34 1.3 +++ cluster/gfs-kernel/src/gfs/ioctl.h 2008/01/24 21:25:41 1.3.6.1 @@ -14,6 +14,9 @@ #ifndef __IOCTL_DOT_H__ #define __IOCTL_DOT_H__ +int gfs_ioctl_i_local(struct gfs_inode *ip, struct gfs_ioctl *gi, + const char *arg0, int from_user); +int gfs_ioctl_i_compat(struct gfs_inode *ip, unsigned long arg); int gfs_ioctl_i(struct gfs_inode *ip, void *arg); #endif /* __IOCTL_DOT_H__ */ --- cluster/gfs-kernel/src/gfs/ops_file.c 2007/06/17 02:56:43 1.28.2.2 +++ cluster/gfs-kernel/src/gfs/ops_file.c 2008/01/24 21:25:41 1.28.2.2.2.1 @@ -26,6 +26,7 @@ #include <linux/aio.h> #include <linux/writeback.h> #include <asm/uaccess.h> +#include <linux/compat.h> #include "gfs_ioctl.h" #include "gfs.h" @@ -1356,8 +1357,43 @@ default: return -ENOTTY; - } + } +} + +#ifdef CONFIG_COMPAT +/** + * gfs_compat_ioctl - do an ioctl on a file - compatible between 32-64 bit + * @inode: the inode + * @file: the file pointer + * @cmd: the ioctl command + * @arg: the argument + * + * Returns: errno + */ + +static long +gfs_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + + atomic_inc(&ip->i_sbd->sd_ops_file); + + switch (cmd) { + case GFS_IOCTL_IDENTIFY: { + unsigned int x = GFS_MAGIC; + if (copy_to_user((unsigned int *)arg, &x, sizeof(unsigned int))) + return -EFAULT; + return 0; + } + + case GFS_IOCTL_SUPER: + return gfs_ioctl_i_compat(ip, arg); + + default: + return -ENOTTY; + } } +#endif /** * gfs_mmap - We don't support shared writable mappings right now @@ -1563,27 +1599,27 @@ if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) - return -ENOLCK; + if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + return -ENOLCK; - if (sdp->sd_args.ar_localflocks) { - if (IS_GETLK(cmd)) { - int conflict; - struct file_lock tmp; - - conflict = posix_test_lock(file, fl, &tmp); - fl->fl_type = F_UNLCK; - if (conflict) - memcpy(fl, &tmp, sizeof(struct file_lock)); - return 0; - } else { - return posix_lock_file_wait(file, fl); - } - } + if (sdp->sd_args.ar_localflocks) { + if (IS_GETLK(cmd)) { + int conflict; + struct file_lock tmp; + + conflict = posix_test_lock(file, fl, &tmp); + fl->fl_type = F_UNLCK; + if (conflict) + memcpy(fl, &tmp, sizeof(struct file_lock)); + return 0; + } else { + return posix_lock_file_wait(file, fl); + } + } - if (IS_GETLK(cmd)) - return gfs_lm_plock_get(sdp, &name, file, fl); - else if (fl->fl_type == F_UNLCK) + if (IS_GETLK(cmd)) + return gfs_lm_plock_get(sdp, &name, file, fl); + else if (fl->fl_type == F_UNLCK) return gfs_lm_punlock(sdp, &name, file, fl); else return gfs_lm_plock(sdp, &name, file, cmd, fl); @@ -1721,22 +1757,22 @@ static int gfs_flock(struct file *file, int cmd, struct file_lock *fl) { - struct gfs_inode *ip = get_v2ip(file->f_mapping->host); - struct gfs_sbd *sdp = ip->i_sbd; + struct gfs_inode *ip = get_v2ip(file->f_mapping->host); + struct gfs_sbd *sdp = ip->i_sbd; - atomic_inc(&ip->i_sbd->sd_ops_file); + atomic_inc(&ip->i_sbd->sd_ops_file); if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) - return -ENOLCK; + if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + return -ENOLCK; - if (sdp->sd_args.ar_localflocks) - return flock_lock_file_wait(file, fl); + if (sdp->sd_args.ar_localflocks) + return flock_lock_file_wait(file, fl); - if (fl->fl_type == F_UNLCK) { - do_unflock(file, fl); - return 0; + if (fl->fl_type == F_UNLCK) { + do_unflock(file, fl); + return 0; } else return do_flock(file, cmd, fl); } @@ -1747,10 +1783,13 @@ .write = gfs_write, .aio_read = gfs_aio_read, .aio_write = gfs_aio_write, - .ioctl = gfs_ioctl, - .mmap = gfs_mmap, - .open = gfs_open, - .release = gfs_close, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .mmap = gfs_mmap, + .open = gfs_open, + .release = gfs_close, .fsync = gfs_fsync, .lock = gfs_lock, .sendfile = gfs_sendfile, @@ -1758,11 +1797,14 @@ }; struct file_operations gfs_dir_fops = { - .readdir = gfs_readdir, - .ioctl = gfs_ioctl, - .open = gfs_open, - .release = gfs_close, - .fsync = gfs_fsync, - .lock = gfs_lock, - .flock = gfs_flock, + .readdir = gfs_readdir, + .ioctl = gfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gfs_compat_ioctl, +#endif + .open = gfs_open, + .release = gfs_close, + .fsync = gfs_fsync, + .lock = gfs_lock, + .flock = gfs_flock, };