Tristan Ye
2009-Nov-27 08:24 UTC
[Ocfs2-devel] [PATCH 1/2] Ocfs2: Add new ioctls prototype and corresponding data structure to ocfs2 header.
We use OCFS2_IOC_INFO to manipulate the new ioctl, the requests can
be stored in a array of (struct ocfs2_info_request), which should be
NULL-terminated, kernel therefore can recoginze and fill them one by
one.
The reason why we need these ioctls is to offer the none-privileged
end-user a possibility to get filesys info gathering.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the first version include following request type:
OCFS2_INFO_CLUSTERSIZE,
OCFS2_INFO_BLOCKSIZE,
OCFS2_INFO_SLOTNUM,
OCFS2_INFO_LABEL,
OCFS2_INFO_UUID,
OCFS2_INFO_FS_FEATURES
It may be grown from time to time:)
Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
fs/ocfs2/ocfs2_fs.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index e9431e4..dac7f4c 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -309,6 +309,75 @@ struct reflink_arguments {
};
#define OCFS2_IOC_REFLINK _IOW('o', 4, struct reflink_arguments)
+#define OCFS2_UUID_LEN 16
+#define OCFS2_MAX_LABEL_LEN 64
+
+/*
+ * Used to query fs information for none-privileged
+ * users by using OCFS2_IOC_INFO ioctols, a series of
+ * following requests need to be NULL-terminated.
+ *
+ * Always try to separate info request into small pieces to
+ * guarantee the backward&forward compatibility.
+ */
+struct ocfs2_info_request {
+ __u32 ir_code; /* Info request code */
+ __u32 ir_flags; /* Request flags */
+};
+
+struct ocfs2_info_request_clustersize {
+ struct ocfs2_info_request ir_request;
+ __u32 ir_clustersize;
+};
+
+struct ocfs2_info_request_blocksize {
+ struct ocfs2_info_request ir_request;
+ __u32 ir_blocksize;
+};
+
+struct ocfs2_info_request_slotnum {
+ struct ocfs2_info_request ir_request;
+ __u16 ir_slotnum;
+};
+
+struct ocfs2_info_request_label {
+ struct ocfs2_info_request ir_request;
+ __u8 ir_label[OCFS2_MAX_LABEL_LEN];
+};
+
+struct ocfs2_info_request_uuid {
+ struct ocfs2_info_request ir_request;
+ __u8 ir_uuid[OCFS2_UUID_LEN];
+};
+
+struct ocfs2_info_request_fs_features {
+ struct ocfs2_info_request ir_quest;
+ __u32 ir_compat_features;
+ __u32 ir_incompat_features;
+ __u32 ir_ro_compat_features;
+};
+
+/* Codes for cfs2_info_request */
+
+#define OCFS2_INFO_CLUSTERSIZE 0x00000001
+#define OCFS2_INFO_BLOCKSIZE 0x00000002
+#define OCFS2_INFO_SLOTNUM 0x00000004
+#define OCFS2_INFO_LABEL 0x00000008
+#define OCFS2_INFO_UUID 0x00000010
+#define OCFS2_INFO_FS_FEATURES 0x00000020
+
+/* Flags for struct ocfs2_info_request */
+/* Filled by the caller */
+#define OCFS2_INFO_FL_NON_COHERENT 0x00000001 /* Cluster coherency not
required.
+ This is a hint. It is up to
+ ocfs2 whether the request can
+ be fulfilled without locking. */
+/* Filled by ocfs2 */
+#define OCFS2_INFO_FL_FILLED 0x80000000 /* Filesystem understood this
+ request and filled in the
+ answer */
+
+#define OCFS2_IOC_INFO _IOR('o', 5, struct ocfs2_info_request)
/*
* Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
--
1.5.5
Tristan Ye
2009-Nov-27 08:24 UTC
[Ocfs2-devel] [PATCH 2/2] Ocfs2: Implement new OCFS2_IOC_INFO ioctl for ocfs2.
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
Sunil Mushran
2009-Nov-30 22:57 UTC
[Ocfs2-devel] [PATCH 1/2] Ocfs2: Add new ioctls prototype and corresponding data structure to ocfs2 header.
Tristan Ye wrote:> We use OCFS2_IOC_INFO to manipulate the new ioctl, the requests can > be stored in a array of (struct ocfs2_info_request), which should be > NULL-terminated, kernel therefore can recoginze and fill them one by > one. > > The reason why we need these ioctls is to offer the none-privileged > end-user a possibility to get filesys info gathering. > > Idea here is to make the spearated request small enough to guarantee > a better backward&forward compatibility since a small piece of request > would be less likely to be broken if filesys on raw disk get changed. > > Currently, the first version include following request type: > > OCFS2_INFO_CLUSTERSIZE, > OCFS2_INFO_BLOCKSIZE, > OCFS2_INFO_SLOTNUM, > OCFS2_INFO_LABEL, > OCFS2_INFO_UUID, > OCFS2_INFO_FS_FEATURES > > It may be grown from time to time:) > > Signed-off-by: Tristan Ye <tristan.ye at oracle.com> > --- > fs/ocfs2/ocfs2_fs.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 69 insertions(+), 0 deletions(-) > > diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h > index e9431e4..dac7f4c 100644 > --- a/fs/ocfs2/ocfs2_fs.h > +++ b/fs/ocfs2/ocfs2_fs.h > @@ -309,6 +309,75 @@ struct reflink_arguments { > }; > #define OCFS2_IOC_REFLINK _IOW('o', 4, struct reflink_arguments) > > +#define OCFS2_UUID_LEN 16 > +#define OCFS2_MAX_LABEL_LEN 64 >What's wrong with the existing OCFS2_MAX_VOL_LABEL_LEN? For UUID, maybe define: #define OCFS2_VOL_UUIDSTR_LEN (OCFS2_VOL_UUID_LEN * 2 + 1)> + > +/* > + * Used to query fs information for none-privileged > + * users by using OCFS2_IOC_INFO ioctols, a series of > + * following requests need to be NULL-terminated. > + * > + * Always try to separate info request into small pieces to > + * guarantee the backward&forward compatibility. > + */ > +struct ocfs2_info_request { > + __u32 ir_code; /* Info request code */ > + __u32 ir_flags; /* Request flags */ > +}; > +Rename it ocfs2_info. Then you have ocfs2_info_clustersize. In the next patch you have typedef-ed these structures presumably because the structure name is long. Instead, shorten the name and use it as is. BTW, typedef-ing struct is strongly discouraged in the kernel coding standards. For good reason.> +struct ocfs2_info_request_clustersize { > + struct ocfs2_info_request ir_request; > + __u32 ir_clustersize; > +}; > + > +struct ocfs2_info_request_blocksize { > + struct ocfs2_info_request ir_request; > + __u32 ir_blocksize; > +}; > + > +struct ocfs2_info_request_slotnum { > + struct ocfs2_info_request ir_request; > + __u16 ir_slotnum; > +}; > + > +struct ocfs2_info_request_label { > + struct ocfs2_info_request ir_request; > + __u8 ir_label[OCFS2_MAX_LABEL_LEN]; > +}; > + > +struct ocfs2_info_request_uuid { > + struct ocfs2_info_request ir_request; > + __u8 ir_uuid[OCFS2_UUID_LEN]; > +}; >Return the uuid string as that is what we use everywhere.> + > +struct ocfs2_info_request_fs_features { > + struct ocfs2_info_request ir_quest; > + __u32 ir_compat_features; > + __u32 ir_incompat_features; > + __u32 ir_ro_compat_features; > +}; > + > +/* Codes for cfs2_info_request */ > + > +#define OCFS2_INFO_CLUSTERSIZE 0x00000001 > +#define OCFS2_INFO_BLOCKSIZE 0x00000002 > +#define OCFS2_INFO_SLOTNUM 0x00000004 > +#define OCFS2_INFO_LABEL 0x00000008 > +#define OCFS2_INFO_UUID 0x00000010 > +#define OCFS2_INFO_FS_FEATURES 0x00000020 >Fix typos, white-spaces, etc. Make use of tabs.> + > +/* Flags for struct ocfs2_info_request */ > +/* Filled by the caller */ > +#define OCFS2_INFO_FL_NON_COHERENT 0x00000001 /* Cluster coherency not required. > + This is a hint. It is up to > + ocfs2 whether the request can > + be fulfilled without locking. */ > +/* Filled by ocfs2 */ > +#define OCFS2_INFO_FL_FILLED 0x80000000 /* Filesystem understood this > + request and filled in the > + answer */ > + > +#define OCFS2_IOC_INFO _IOR('o', 5, struct ocfs2_info_request) > > /* > * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) >