Commit b9598db3401282bb27b4aef77e3eee12015f7f29

Authored by Jens Axboe
1 parent 0191f8697b

pipe: make F_{GET,SET}PIPE_SZ deal with byte sizes

Instead of requiring an exact number of pages as the argument and
return value, change the API to deal with number of bytes instead.

This also relaxes the requirement that the passed in size must
result in a power-of-2 page array size. Round up to the nearest
power-of-2 automatically and return the resulting size of the pipe
on success.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 1 changed file with 21 additions and 16 deletions Side-by-side Diff

... ... @@ -1112,26 +1112,20 @@
1112 1112 * Allocate a new array of pipe buffers and copy the info over. Returns the
1113 1113 * pipe size if successful, or return -ERROR on error.
1114 1114 */
1115   -static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
  1115 +static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
1116 1116 {
1117 1117 struct pipe_buffer *bufs;
1118 1118  
1119 1119 /*
1120   - * Must be a power-of-2 currently
1121   - */
1122   - if (!is_power_of_2(arg))
1123   - return -EINVAL;
1124   -
1125   - /*
1126 1120 * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
1127 1121 * expect a lot of shrink+grow operations, just free and allocate
1128 1122 * again like we would do for growing. If the pipe currently
1129 1123 * contains more buffers than arg, then return busy.
1130 1124 */
1131   - if (arg < pipe->nrbufs)
  1125 + if (nr_pages < pipe->nrbufs)
1132 1126 return -EBUSY;
1133 1127  
1134   - bufs = kcalloc(arg, sizeof(struct pipe_buffer), GFP_KERNEL);
  1128 + bufs = kcalloc(nr_pages, sizeof(struct pipe_buffer), GFP_KERNEL);
1135 1129 if (unlikely(!bufs))
1136 1130 return -ENOMEM;
1137 1131  
... ... @@ -1152,8 +1146,8 @@
1152 1146 pipe->curbuf = 0;
1153 1147 kfree(pipe->bufs);
1154 1148 pipe->bufs = bufs;
1155   - pipe->buffers = arg;
1156   - return arg;
  1149 + pipe->buffers = nr_pages;
  1150 + return nr_pages * PAGE_SIZE;
1157 1151 }
1158 1152  
1159 1153 long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
1160 1154  
1161 1155  
1162 1156  
1163 1157  
1164 1158  
... ... @@ -1168,19 +1162,30 @@
1168 1162 mutex_lock(&pipe->inode->i_mutex);
1169 1163  
1170 1164 switch (cmd) {
1171   - case F_SETPIPE_SZ:
1172   - if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages)
  1165 + case F_SETPIPE_SZ: {
  1166 + unsigned long nr_pages;
  1167 +
  1168 + /*
  1169 + * Currently the array must be a power-of-2 size, so adjust
  1170 + * upwards if needed.
  1171 + */
  1172 + nr_pages = (arg + PAGE_SIZE - 1) >> PAGE_SHIFT;
  1173 + nr_pages = roundup_pow_of_two(nr_pages);
  1174 +
  1175 + if (!capable(CAP_SYS_ADMIN) && nr_pages > pipe_max_pages)
1173 1176 return -EPERM;
  1177 +
1174 1178 /*
1175 1179 * The pipe needs to be at least 2 pages large to
1176 1180 * guarantee POSIX behaviour.
1177 1181 */
1178   - if (arg < 2)
  1182 + if (nr_pages < 2)
1179 1183 return -EINVAL;
1180   - ret = pipe_set_size(pipe, arg);
  1184 + ret = pipe_set_size(pipe, nr_pages);
1181 1185 break;
  1186 + }
1182 1187 case F_GETPIPE_SZ:
1183   - ret = pipe->buffers;
  1188 + ret = pipe->buffers * PAGE_SIZE;
1184 1189 break;
1185 1190 default:
1186 1191 ret = -EINVAL;