[Cluster-devel] cluster/gfs-kernel/src/gfs gfs_ioctl.h ioctl.c ...
rpeterso at sourceware.org
rpeterso at sourceware.org
Thu Jan 24 20:54:32 UTC 2008
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: rpeterso at sourceware.org 2008-01-24 20:54:31
Modified files:
gfs-kernel/src/gfs: gfs_ioctl.h ioctl.c ioctl.h ops_file.c
Log message:
Resolves: bz 429633: 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&r1=1.11&r2=1.12
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.c.diff?cvsroot=cluster&r1=1.17&r2=1.18
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.h.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_file.c.diff?cvsroot=cluster&r1=1.36&r2=1.37
--- 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 20:54:31 1.12
@@ -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 21:26:11 1.17
+++ cluster/gfs-kernel/src/gfs/ioctl.c 2008/01/24 20:54:31 1.18
@@ -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,58 +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, "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);
- 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 20:54:31 1.4
@@ -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/07/13 15:19:16 1.36
+++ cluster/gfs-kernel/src/gfs/ops_file.c 2008/01/24 20:54:31 1.37
@@ -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"
@@ -333,17 +334,17 @@
goto out_gunlock;
count = do_read_readi(file, buf, size & ~mask, offset, iocb);
- }
- else {
- if (!iocb)
- count = do_sync_read(file, buf, size, offset);
- else {
- struct iovec local_iov = { .iov_base = buf, .iov_len = size};
-
- count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
- iocb->ki_pos = *offset;
- }
- }
+ }
+ else {
+ if (!iocb)
+ count = do_sync_read(file, buf, size, offset);
+ else {
+ struct iovec local_iov = { .iov_base = buf, .iov_len = size};
+
+ count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
+ iocb->ki_pos = *offset;
+ }
+ }
error = 0;
@@ -387,17 +388,17 @@
if (gfs_is_jdata(ip) ||
(gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags)))
- count = do_read_readi(file, buf, size, offset, iocb);
- else {
- if (!iocb) {
- count = do_sync_read(file, buf, size, offset);
- } else {
- struct iovec local_iov = { .iov_base = buf, .iov_len = size};
-
- count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
- iocb->ki_pos = *offset;
- }
- }
+ count = do_read_readi(file, buf, size, offset, iocb);
+ else {
+ if (!iocb) {
+ count = do_sync_read(file, buf, size, offset);
+ } else {
+ struct iovec local_iov = { .iov_base = buf, .iov_len = size};
+
+ count = generic_file_aio_read(iocb, &local_iov, 1, *offset);
+ iocb->ki_pos = *offset;
+ }
+ }
gfs_glock_dq_m(num_gh + 1, ghs);
@@ -438,16 +439,16 @@
/*
* gfs_aio_read: match with vfs generic_file_aio_read as:
- * (struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+ * (struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
*/
static ssize_t
gfs_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long count,
- loff_t pos)
+ loff_t pos)
{
- struct file *filp = iocb->ki_filp;
+ struct file *filp = iocb->ki_filp;
- BUG_ON(iocb->ki_pos != pos);
- return(__gfs_read(filp, iov->iov_base, iov->iov_len, &iocb->ki_pos, iocb));
+ BUG_ON(iocb->ki_pos != pos);
+ return(__gfs_read(filp, iov->iov_base, iov->iov_len, &iocb->ki_pos, iocb));
}
/**
@@ -493,27 +494,27 @@
*/
static ssize_t
gfs_file_aio_write_nolock(struct file *file, char *buf, size_t size,
- loff_t *offset, struct kiocb *iocb)
+ loff_t *offset, struct kiocb *iocb)
{
- struct iovec local_iov = { .iov_base = buf, .iov_len = size };
- struct kiocb local_iocb, *kiocb = NULL;
- ssize_t count;
-
- if (!iocb) {
- init_sync_kiocb(&local_iocb, file);
- local_iocb.ki_nr_segs = 1;
- kiocb = &local_iocb;
- }
- else
- kiocb = iocb;
-
- kiocb->ki_pos = *offset;
- count = generic_file_aio_write_nolock(kiocb, &local_iov, kiocb->ki_nr_segs,
- kiocb->ki_pos);
- *offset = kiocb->ki_pos;
- if (kiocb == &local_iocb && count == -EIOCBQUEUED)
- count = wait_on_sync_kiocb(kiocb);
- return count;
+ struct iovec local_iov = { .iov_base = buf, .iov_len = size };
+ struct kiocb local_iocb, *kiocb = NULL;
+ ssize_t count;
+
+ if (!iocb) {
+ init_sync_kiocb(&local_iocb, file);
+ local_iocb.ki_nr_segs = 1;
+ kiocb = &local_iocb;
+ }
+ else
+ kiocb = iocb;
+
+ kiocb->ki_pos = *offset;
+ count = generic_file_aio_write_nolock(kiocb, &local_iov, kiocb->ki_nr_segs,
+ kiocb->ki_pos);
+ *offset = kiocb->ki_pos;
+ if (kiocb == &local_iocb && count == -EIOCBQUEUED)
+ count = wait_on_sync_kiocb(kiocb);
+ return count;
}
/**
@@ -533,12 +534,12 @@
struct kiocb *iocb)
{
struct inode *inode = file->f_mapping->host;
- struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_alloc *al = NULL;
- struct buffer_head *dibh;
- unsigned int data_blocks, ind_blocks;
- ssize_t count;
+ struct gfs_inode *ip = get_v2ip(inode);
+ struct gfs_sbd *sdp = ip->i_sbd;
+ struct gfs_alloc *al = NULL;
+ struct buffer_head *dibh;
+ unsigned int data_blocks, ind_blocks;
+ ssize_t count;
int error;
gfs_write_calc_reserv(ip, size, &data_blocks, &ind_blocks);
@@ -583,13 +584,13 @@
}
if (gfs_is_stuffed(ip)) { error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); if (error)
- goto fail_end_trans;
- }
+ goto fail_end_trans;
+ }
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- if (count < 0) {
- error = count;
- goto fail_end_trans;
+ count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
+ if (count < 0) {
+ error = count;
+ goto fail_end_trans;
}
error = gfs_get_inode_buffer(ip, &dibh);
@@ -747,23 +748,23 @@
buf += error;
size -= error;
- count += error;
- }
- } else {
- struct gfs_holder t_gh;
+ count += error;
+ }
+ } else {
+ struct gfs_holder t_gh;
- clear_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags);
+ clear_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags);
error = gfs_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh);
if (error)
goto out_gunlock;
- /* Todo: It would be nice if init_sync_kiocb is exported.
- * .. wcheng
- */
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- gfs_glock_dq_uninit(&t_gh);
- }
+ /* Todo: It would be nice if init_sync_kiocb is exported.
+ * .. wcheng
+ */
+ count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
+ gfs_glock_dq_uninit(&t_gh);
+ }
out_iocb_write:
error = 0;
@@ -881,13 +882,13 @@
ClearPageUptodate(page);
page_cache_release(page);
}
- }
- *offset += count;
- } else {
- count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
- if (count < 0) {
- error = count;
- goto fail_end_trans;
+ }
+ *offset += count;
+ } else {
+ count = gfs_file_aio_write_nolock(file, buf, size, offset, iocb);
+ if (count < 0) {
+ error = count;
+ goto fail_end_trans;
}
error = gfs_get_inode_buffer(ip, &dibh);
@@ -1061,14 +1062,14 @@
static ssize_t
gfs_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long segs,
- loff_t pos)
+ loff_t pos)
{
- struct file *file = iocb->ki_filp;
+ struct file *file = iocb->ki_filp;
- BUG_ON(iocb->ki_pos != pos);
+ BUG_ON(iocb->ki_pos != pos);
- return(__gfs_write(file, iov->iov_base, iov->iov_len, &iocb->ki_pos,
- iocb));
+ return(__gfs_write(file, iov->iov_base, iov->iov_len, &iocb->ki_pos,
+ iocb));
}
/**
@@ -1373,6 +1374,41 @@
}
}
+#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
* @file: The file to map
@@ -1577,24 +1613,24 @@
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)) {
- posix_test_lock(file, fl);
- return 0;
- } else {
- return posix_lock_file_wait(file, fl);
- }
- }
+ if (sdp->sd_args.ar_localflocks) {
+ if (IS_GETLK(cmd)) {
+ posix_test_lock(file, fl);
+ 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);
+ return gfs_lm_plock(sdp, &name, file, cmd, fl);
}
#if 0
@@ -1635,7 +1671,7 @@
out:
gfs_holder_uninit(&gh);
- return retval;
+ return retval;
}
#endif
@@ -1731,22 +1767,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);
}
@@ -1758,21 +1794,27 @@
.aio_read = gfs_aio_read,
.aio_write = gfs_aio_write,
.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, */
- .flock = gfs_flock,
+ .release = gfs_close,
+ .fsync = gfs_fsync,
+ .lock = gfs_lock,
+ /* .sendfile = gfs_sendfile, */
+ .flock = gfs_flock,
};
struct file_operations gfs_dir_fops = {
.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,
+ .lock = gfs_lock,
+ .flock = gfs_flock,
};
More information about the Cluster-devel
mailing list