[Ocfs2-devel] [PATCH 2/2] Ocfs2: Implement new OCFS2_IOC_INFO ioctl for ocfs2.

Tristan Ye tristan.ye at oracle.com
Fri Nov 27 00:24:36 PST 2009


We implement the request as simple as possible to avoid
a possible extending if disk format get changed.

Completenss of a request include the info required and a flag(FL_FILLED)
filled being returned to the end-user.

Note: the requests in a series from userspace should be NULL-terminated.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 fs/ocfs2/ioctl.c |  184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 184 insertions(+), 0 deletions(-)

diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index 31fbb06..0ac5218 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -108,6 +108,188 @@ bail:
 	return status;
 }
 
+static int ocfs2_get_request_info(struct inode *inode,
+				  unsigned long arg)
+{
+
+	int ret = 0, i = 0, num_reqs = 0;
+
+	struct ocfs2_info_request req, *preq = NULL;
+	struct ocfs2_info_request **reqs;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	typedef struct ocfs2_info_request OIR, *POIR;
+	typedef struct ocfs2_info_request_clustersize OIRC, *POIRC;
+	typedef struct ocfs2_info_request_blocksize OIRB, *POIRB;
+	typedef struct ocfs2_info_request_slotnum OIRS, *POIRS;
+	typedef struct ocfs2_info_request_label OIRL, *POIRL;
+	typedef struct ocfs2_info_request_uuid OIRU, *POIRU;
+	typedef struct ocfs2_info_request_fs_features OIRF, *POIRF;
+
+	/*
+	 * The requests series from userspace need to be NULL-terminated.
+	 */
+	do {
+		preq = *((POIR *)((char *)arg + i * sizeof(POIR)));
+		if (!preq)
+			break;
+		i++;
+
+	} while (preq);
+
+	num_reqs = i;
+
+	reqs = kmalloc(sizeof(POIR) * num_reqs, GFP_KERNEL);
+	if (!reqs) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	ret = ocfs2_inode_lock(inode, NULL, 0);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	for (i = 0; i < num_reqs; i++) {
+
+		reqs[i] = NULL;
+
+		preq = *((POIR *)((char *)arg + i * sizeof(POIR)));
+
+		if (copy_from_user(&req, preq, sizeof(req))) {
+			ret = -EFAULT;
+			goto bail;
+		}
+
+		switch (req.ir_code) {
+		case OCFS2_INFO_CLUSTERSIZE:
+			reqs[i] = kmalloc(sizeof(OIRC), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRC))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			((POIRC)(reqs[i]))->ir_clustersize = osb->s_clustersize;
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRC))) {
+				ret = EFAULT;
+				goto bail;
+			}
+
+			break;
+		case OCFS2_INFO_BLOCKSIZE:
+			reqs[i] = kmalloc(sizeof(OIRB), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRB))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			((POIRB)(reqs[i]))->ir_blocksize =
+					inode->i_sb->s_blocksize;
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRB))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			break;
+		case OCFS2_INFO_SLOTNUM:
+			reqs[i] = kmalloc(sizeof(OIRS), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRS))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			((POIRS)(reqs[i]))->ir_slotnum = osb->max_slots;
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRS))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			break;
+		case OCFS2_INFO_LABEL:
+			reqs[i] = kmalloc(sizeof(OIRL), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRL))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			memmove(((POIRL)(reqs[i]))->ir_label, osb->vol_label,
+				OCFS2_MAX_VOL_LABEL_LEN);
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRL))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			break;
+		case OCFS2_INFO_UUID:
+			reqs[i] = kmalloc(sizeof(OIRU), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRU))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			memmove(((POIRU)(reqs[i]))->ir_uuid, osb->uuid,
+				OCFS2_VOL_UUID_LEN);
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRU))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			break;
+		case OCFS2_INFO_FS_FEATURES:
+			reqs[i] = kmalloc(sizeof(OIRF), GFP_KERNEL);
+
+			if (copy_from_user(reqs[i], preq, sizeof(OIRF))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			((POIRF)(reqs[i]))->ir_compat_features =
+						osb->s_feature_compat;
+			((POIRF)(reqs[i]))->ir_incompat_features =
+						osb->s_feature_incompat;
+			((POIRF)(reqs[i]))->ir_ro_compat_features =
+						osb->s_feature_ro_compat;
+			reqs[i]->ir_flags |= OCFS2_INFO_FL_FILLED;
+
+			if (copy_to_user(preq, reqs[i], sizeof(OIRF))) {
+				ret = -EFAULT;
+				goto bail;
+			}
+
+			break;
+		default:
+			break;
+		}
+
+	}
+bail:
+	for (i = 0; i < num_reqs; i++)
+		kfree(reqs[i]);
+
+	kfree(reqs);
+
+	ocfs2_inode_unlock(inode, 0);
+
+	mlog_exit(ret);
+	return ret;
+}
+
 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
@@ -173,6 +355,8 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		preserve = (args.preserve != 0);
 
 		return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
+	case OCFS2_IOC_INFO:
+		return ocfs2_get_request_info(inode, arg);
 	default:
 		return -ENOTTY;
 	}
-- 
1.5.5




More information about the Ocfs2-devel mailing list