Skip to contentSkip to conversation

staging/lustre: clean up and remove libcfs/linux/linux-fs.c

PATCH Peng Tao 1 participant 2 messages Jun 4, 2013 3 messages not in the archive Btrfs file system

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 20130604083206.GL28112@mwanda

Peng Tao

author
#3 lore raw
Quoted 31 lines · Dan Carpenter
Quoted 30 lines · Peng Tao

int libcfs_kkuc_msg_put(struct file *filp, void *payload)

 {
      struct kuc_hdr *kuch = (struct kuc_hdr *)payload;
(quoted diff) +14 -4
+     ssize_t count = kuch->kuc_msglen;
+     loff_t offset = 0;
+     mm_segment_t fs;
      int rc = -ENOSYS;
 
      if (filp == NULL || IS_ERR(filp))
@@ -165,11 +168,18 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload)
              return -ENOSYS;
      }
 
-     {
-             loff_t offset = 0;
-             rc = filp_user_write(filp, payload, kuch->kuc_msglen,
-                                  &offset);
+     fs = get_fs();
+     set_fs(KERNEL_DS);
+     while ((ssize_t)count > 0) {
+             rc = vfs_write(filp, (const void __user *)payload,
+                            count, &offset);
+             if (rc < 0)
+                     break;
+             count -= rc;
+             payload += rc;
+             rc = 0;
      }
+     set_fs(fs);
 
Quoted 8 lines

Review int libcfs_kkuc_msg_put(struct file *filp, void *payload) · line 185

Quoted 2 lines
(quoted diff) +0 -0
      if (rc < 0)
              CWARN("message send failed (%d)\n", rc);

This was all there in the original code, it has just been shifted. Still, I had some questions about it. "payload" is a pointer to kernel stack memory, wouldn't the access_ok() check in vfs_write() fail every time on x86?

Thanks for reviewing. I am not familiar with access_ok() but I think you are right and I'll test to see if it really breaks. In the meantime, I took a look at other kernel callers of vfs_write() and btrfs is also calling vfs_write() to write kernel stack memory (fs/btrfs/send.c: send_header->write_buf->vfs_write). So I CC'ed btrfs list in case someone knows better than I do.

Quoted 5 lines

Some of the casting is not needed. No need to cast "count" because it is already ssize_t. I haven't tested but I think Sparse will complain about the __user cast until __force is added. No need for the cast to const.

Thanks. I will fix it.

Quoted 4 lines

I worry about partial writes and that this could be a forever loop but I don't know enough about anything to say if that's possible. Probably not.

For partial writes, both payload and count are advanced properly. So it won't loop forever.

Thanks,
Tao

author
#4 lore raw
Quoted 32 lines · Peng Tao
Quoted 31 lines · Dan Carpenter
Quoted 30 lines · Peng Tao

int libcfs_kkuc_msg_put(struct file *filp, void *payload)

 {
      struct kuc_hdr *kuch = (struct kuc_hdr *)payload;
(quoted diff) +14 -4
+     ssize_t count = kuch->kuc_msglen;
+     loff_t offset = 0;
+     mm_segment_t fs;
      int rc = -ENOSYS;
 
      if (filp == NULL || IS_ERR(filp))
@@ -165,11 +168,18 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload)
              return -ENOSYS;
      }
 
-     {
-             loff_t offset = 0;
-             rc = filp_user_write(filp, payload, kuch->kuc_msglen,
-                                  &offset);
+     fs = get_fs();
+     set_fs(KERNEL_DS);
+     while ((ssize_t)count > 0) {
+             rc = vfs_write(filp, (const void __user *)payload,
+                            count, &offset);
+             if (rc < 0)
+                     break;
+             count -= rc;
+             payload += rc;
+             rc = 0;
      }
+     set_fs(fs);
 
Quoted 8 lines
Quoted 8 lines

Review int libcfs_kkuc_msg_put(struct file *filp, void *payload) · line 185

Quoted 2 lines
(quoted diff) +0 -0
      if (rc < 0)
              CWARN("message send failed (%d)\n", rc);

This was all there in the original code, it has just been shifted. Still, I had some questions about it. "payload" is a pointer to kernel stack memory, wouldn't the access_ok() check in vfs_write() fail every time on x86?

I've run some tests and it turns out that access_ok() doesn't deny vfs_write() when passed in allocated kernel memory (e.g., mdc_wr_kuc()). There is indeed a bug in mdc_wr_kuc() for which I will send a fix later. However, I cannot test the specific stack memory write path because of a known issue of Lustre
(https://jira.hpdd.intel.com/browse/LU-2489). And FYI, the Lustre hsm feature is still under development.

Thanks,
Tao

Quoted 23 lines

Thanks for reviewing. I am not familiar with access_ok() but I think you are right and I'll test to see if it really breaks. In the meantime, I took a look at other kernel callers of vfs_write() and btrfs is also calling vfs_write() to write kernel stack memory (fs/btrfs/send.c: send_header->write_buf->vfs_write). So I CC'ed btrfs list in case someone knows better than I do.

Quoted 5 lines

Some of the casting is not needed. No need to cast "count" because it is already ssize_t. I haven't tested but I think Sparse will complain about the __user cast until __force is added. No need for the cast to const.

Thanks. I will fix it.

Quoted 4 lines

I worry about partial writes and that this could be a forever loop but I don't know enough about anything to say if that's possible. Probably not.

For partial writes, both payload and count are advanced properly. So it won't loop forever.

Thanks,
Tao