diff options
| -rw-r--r-- | fs/xfs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 305 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.h | 15 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 175 |
4 files changed, 196 insertions, 300 deletions
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index 3f53dd101f99..29228f5899cd 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config XFS_FS | 1 | config XFS_FS |
| 2 | tristate "XFS filesystem support" | 2 | tristate "XFS filesystem support" |
| 3 | depends on BLOCK | 3 | depends on BLOCK |
| 4 | select EXPORTFS | ||
| 4 | help | 5 | help |
| 5 | XFS is a high performance journaling filesystem which originated | 6 | XFS is a high performance journaling filesystem which originated |
| 6 | on the SGI IRIX platform. It is completely multi-threaded, can | 7 | on the SGI IRIX platform. It is completely multi-threaded, can |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index e5be1e0be802..4bd112313f33 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
| @@ -50,12 +50,14 @@ | |||
| 50 | #include "xfs_vnodeops.h" | 50 | #include "xfs_vnodeops.h" |
| 51 | #include "xfs_quota.h" | 51 | #include "xfs_quota.h" |
| 52 | #include "xfs_inode_item.h" | 52 | #include "xfs_inode_item.h" |
| 53 | #include "xfs_export.h" | ||
| 53 | 54 | ||
| 54 | #include <linux/capability.h> | 55 | #include <linux/capability.h> |
| 55 | #include <linux/dcache.h> | 56 | #include <linux/dcache.h> |
| 56 | #include <linux/mount.h> | 57 | #include <linux/mount.h> |
| 57 | #include <linux/namei.h> | 58 | #include <linux/namei.h> |
| 58 | #include <linux/pagemap.h> | 59 | #include <linux/pagemap.h> |
| 60 | #include <linux/exportfs.h> | ||
| 59 | 61 | ||
| 60 | /* | 62 | /* |
| 61 | * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to | 63 | * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to |
| @@ -164,97 +166,69 @@ xfs_find_handle( | |||
| 164 | return 0; | 166 | return 0; |
| 165 | } | 167 | } |
| 166 | 168 | ||
| 167 | |||
| 168 | /* | 169 | /* |
| 169 | * Convert userspace handle data into inode. | 170 | * No need to do permission checks on the various pathname components |
| 170 | * | 171 | * as the handle operations are privileged. |
| 171 | * We use the fact that all the fsop_handlereq ioctl calls have a data | ||
| 172 | * structure argument whose first component is always a xfs_fsop_handlereq_t, | ||
| 173 | * so we can pass that sub structure into this handy, shared routine. | ||
| 174 | * | ||
| 175 | * If no error, caller must always iput the returned inode. | ||
| 176 | */ | 172 | */ |
| 177 | STATIC int | 173 | STATIC int |
| 178 | xfs_vget_fsop_handlereq( | 174 | xfs_handle_acceptable( |
| 179 | xfs_mount_t *mp, | 175 | void *context, |
| 180 | struct inode *parinode, /* parent inode pointer */ | 176 | struct dentry *dentry) |
| 181 | xfs_fsop_handlereq_t *hreq, | 177 | { |
| 182 | struct inode **inode) | 178 | return 1; |
| 179 | } | ||
| 180 | |||
| 181 | /* | ||
| 182 | * Convert userspace handle data into a dentry. | ||
| 183 | */ | ||
| 184 | struct dentry * | ||
| 185 | xfs_handle_to_dentry( | ||
| 186 | struct file *parfilp, | ||
| 187 | void __user *uhandle, | ||
| 188 | u32 hlen) | ||
| 183 | { | 189 | { |
| 184 | void __user *hanp; | ||
| 185 | size_t hlen; | ||
| 186 | xfs_fid_t *xfid; | ||
| 187 | xfs_handle_t *handlep; | ||
| 188 | xfs_handle_t handle; | 190 | xfs_handle_t handle; |
| 189 | xfs_inode_t *ip; | 191 | struct xfs_fid64 fid; |
| 190 | xfs_ino_t ino; | ||
| 191 | __u32 igen; | ||
| 192 | int error; | ||
| 193 | 192 | ||
| 194 | /* | 193 | /* |
| 195 | * Only allow handle opens under a directory. | 194 | * Only allow handle opens under a directory. |
| 196 | */ | 195 | */ |
| 197 | if (!S_ISDIR(parinode->i_mode)) | 196 | if (!S_ISDIR(parfilp->f_path.dentry->d_inode->i_mode)) |
| 198 | return XFS_ERROR(ENOTDIR); | 197 | return ERR_PTR(-ENOTDIR); |
| 199 | 198 | ||
| 200 | hanp = hreq->ihandle; | 199 | if (hlen != sizeof(xfs_handle_t)) |
| 201 | hlen = hreq->ihandlen; | 200 | return ERR_PTR(-EINVAL); |
| 202 | handlep = &handle; | 201 | if (copy_from_user(&handle, uhandle, hlen)) |
| 203 | 202 | return ERR_PTR(-EFAULT); | |
| 204 | if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) | 203 | if (handle.ha_fid.fid_len != |
| 205 | return XFS_ERROR(EINVAL); | 204 | sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len)) |
| 206 | if (copy_from_user(handlep, hanp, hlen)) | 205 | return ERR_PTR(-EINVAL); |
| 207 | return XFS_ERROR(EFAULT); | 206 | |
| 208 | if (hlen < sizeof(*handlep)) | 207 | memset(&fid, 0, sizeof(struct fid)); |
| 209 | memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); | 208 | fid.ino = handle.ha_fid.fid_ino; |
| 210 | if (hlen > sizeof(handlep->ha_fsid)) { | 209 | fid.gen = handle.ha_fid.fid_gen; |
| 211 | if (handlep->ha_fid.fid_len != | 210 | |
| 212 | (hlen - sizeof(handlep->ha_fsid) - | 211 | return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3, |
| 213 | sizeof(handlep->ha_fid.fid_len)) || | 212 | FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG, |
| 214 | handlep->ha_fid.fid_pad) | 213 | xfs_handle_acceptable, NULL); |
| 215 | return XFS_ERROR(EINVAL); | 214 | } |
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Crack the handle, obtain the inode # & generation # | ||
| 220 | */ | ||
| 221 | xfid = (struct xfs_fid *)&handlep->ha_fid; | ||
| 222 | if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) { | ||
| 223 | ino = xfid->fid_ino; | ||
| 224 | igen = xfid->fid_gen; | ||
| 225 | } else { | ||
| 226 | return XFS_ERROR(EINVAL); | ||
| 227 | } | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Get the XFS inode, building a Linux inode to go with it. | ||
| 231 | */ | ||
| 232 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0); | ||
| 233 | if (error) | ||
| 234 | return error; | ||
| 235 | if (ip == NULL) | ||
| 236 | return XFS_ERROR(EIO); | ||
| 237 | if (ip->i_d.di_gen != igen) { | ||
| 238 | xfs_iput_new(ip, XFS_ILOCK_SHARED); | ||
| 239 | return XFS_ERROR(ENOENT); | ||
| 240 | } | ||
| 241 | |||
| 242 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
| 243 | 215 | ||
| 244 | *inode = VFS_I(ip); | 216 | STATIC struct dentry * |
| 245 | return 0; | 217 | xfs_handlereq_to_dentry( |
| 218 | struct file *parfilp, | ||
| 219 | xfs_fsop_handlereq_t *hreq) | ||
| 220 | { | ||
| 221 | return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen); | ||
| 246 | } | 222 | } |
| 247 | 223 | ||
| 248 | int | 224 | int |
| 249 | xfs_open_by_handle( | 225 | xfs_open_by_handle( |
| 250 | xfs_mount_t *mp, | ||
| 251 | xfs_fsop_handlereq_t *hreq, | ||
| 252 | struct file *parfilp, | 226 | struct file *parfilp, |
| 253 | struct inode *parinode) | 227 | xfs_fsop_handlereq_t *hreq) |
| 254 | { | 228 | { |
| 255 | const struct cred *cred = current_cred(); | 229 | const struct cred *cred = current_cred(); |
| 256 | int error; | 230 | int error; |
| 257 | int new_fd; | 231 | int fd; |
| 258 | int permflag; | 232 | int permflag; |
| 259 | struct file *filp; | 233 | struct file *filp; |
| 260 | struct inode *inode; | 234 | struct inode *inode; |
| @@ -263,19 +237,21 @@ xfs_open_by_handle( | |||
| 263 | if (!capable(CAP_SYS_ADMIN)) | 237 | if (!capable(CAP_SYS_ADMIN)) |
| 264 | return -XFS_ERROR(EPERM); | 238 | return -XFS_ERROR(EPERM); |
| 265 | 239 | ||
| 266 | error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode); | 240 | dentry = xfs_handlereq_to_dentry(parfilp, hreq); |
| 267 | if (error) | 241 | if (IS_ERR(dentry)) |
| 268 | return -error; | 242 | return PTR_ERR(dentry); |
| 243 | inode = dentry->d_inode; | ||
| 269 | 244 | ||
| 270 | /* Restrict xfs_open_by_handle to directories & regular files. */ | 245 | /* Restrict xfs_open_by_handle to directories & regular files. */ |
| 271 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { | 246 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { |
| 272 | iput(inode); | 247 | error = -XFS_ERROR(EPERM); |
| 273 | return -XFS_ERROR(EINVAL); | 248 | goto out_dput; |
| 274 | } | 249 | } |
| 275 | 250 | ||
| 276 | #if BITS_PER_LONG != 32 | 251 | #if BITS_PER_LONG != 32 |
| 277 | hreq->oflags |= O_LARGEFILE; | 252 | hreq->oflags |= O_LARGEFILE; |
| 278 | #endif | 253 | #endif |
| 254 | |||
| 279 | /* Put open permission in namei format. */ | 255 | /* Put open permission in namei format. */ |
| 280 | permflag = hreq->oflags; | 256 | permflag = hreq->oflags; |
| 281 | if ((permflag+1) & O_ACCMODE) | 257 | if ((permflag+1) & O_ACCMODE) |
| @@ -285,50 +261,45 @@ xfs_open_by_handle( | |||
| 285 | 261 | ||
| 286 | if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && | 262 | if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && |
| 287 | (permflag & FMODE_WRITE) && IS_APPEND(inode)) { | 263 | (permflag & FMODE_WRITE) && IS_APPEND(inode)) { |
| 288 | iput(inode); | 264 | error = -XFS_ERROR(EPERM); |
| 289 | return -XFS_ERROR(EPERM); | 265 | goto out_dput; |
| 290 | } | 266 | } |
| 291 | 267 | ||
| 292 | if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { | 268 | if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { |
| 293 | iput(inode); | 269 | error = -XFS_ERROR(EACCES); |
| 294 | return -XFS_ERROR(EACCES); | 270 | goto out_dput; |
| 295 | } | 271 | } |
| 296 | 272 | ||
| 297 | /* Can't write directories. */ | 273 | /* Can't write directories. */ |
| 298 | if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { | 274 | if (S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { |
| 299 | iput(inode); | 275 | error = -XFS_ERROR(EISDIR); |
| 300 | return -XFS_ERROR(EISDIR); | 276 | goto out_dput; |
| 301 | } | 277 | } |
| 302 | 278 | ||
| 303 | if ((new_fd = get_unused_fd()) < 0) { | 279 | fd = get_unused_fd(); |
| 304 | iput(inode); | 280 | if (fd < 0) { |
| 305 | return new_fd; | 281 | error = fd; |
| 282 | goto out_dput; | ||
| 306 | } | 283 | } |
| 307 | 284 | ||
| 308 | dentry = d_obtain_alias(inode); | 285 | filp = dentry_open(dentry, mntget(parfilp->f_path.mnt), |
| 309 | if (IS_ERR(dentry)) { | 286 | hreq->oflags, cred); |
| 310 | put_unused_fd(new_fd); | ||
| 311 | return PTR_ERR(dentry); | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Ensure umount returns EBUSY on umounts while this file is open. */ | ||
| 315 | mntget(parfilp->f_path.mnt); | ||
| 316 | |||
| 317 | /* Create file pointer. */ | ||
| 318 | filp = dentry_open(dentry, parfilp->f_path.mnt, hreq->oflags, cred); | ||
| 319 | if (IS_ERR(filp)) { | 287 | if (IS_ERR(filp)) { |
| 320 | put_unused_fd(new_fd); | 288 | put_unused_fd(fd); |
| 321 | return -XFS_ERROR(-PTR_ERR(filp)); | 289 | return PTR_ERR(filp); |
| 322 | } | 290 | } |
| 323 | 291 | ||
| 324 | if (inode->i_mode & S_IFREG) { | 292 | if (inode->i_mode & S_IFREG) { |
| 325 | /* invisible operation should not change atime */ | ||
| 326 | filp->f_flags |= O_NOATIME; | 293 | filp->f_flags |= O_NOATIME; |
| 327 | filp->f_mode |= FMODE_NOCMTIME; | 294 | filp->f_mode |= FMODE_NOCMTIME; |
| 328 | } | 295 | } |
| 329 | 296 | ||
| 330 | fd_install(new_fd, filp); | 297 | fd_install(fd, filp); |
| 331 | return new_fd; | 298 | return fd; |
| 299 | |||
| 300 | out_dput: | ||
| 301 | dput(dentry); | ||
| 302 | return error; | ||
| 332 | } | 303 | } |
| 333 | 304 | ||
| 334 | /* | 305 | /* |
| @@ -359,11 +330,10 @@ do_readlink( | |||
| 359 | 330 | ||
| 360 | int | 331 | int |
| 361 | xfs_readlink_by_handle( | 332 | xfs_readlink_by_handle( |
| 362 | xfs_mount_t *mp, | 333 | struct file *parfilp, |
| 363 | xfs_fsop_handlereq_t *hreq, | 334 | xfs_fsop_handlereq_t *hreq) |
| 364 | struct inode *parinode) | ||
| 365 | { | 335 | { |
| 366 | struct inode *inode; | 336 | struct dentry *dentry; |
| 367 | __u32 olen; | 337 | __u32 olen; |
| 368 | void *link; | 338 | void *link; |
| 369 | int error; | 339 | int error; |
| @@ -371,26 +341,28 @@ xfs_readlink_by_handle( | |||
| 371 | if (!capable(CAP_SYS_ADMIN)) | 341 | if (!capable(CAP_SYS_ADMIN)) |
| 372 | return -XFS_ERROR(EPERM); | 342 | return -XFS_ERROR(EPERM); |
| 373 | 343 | ||
| 374 | error = xfs_vget_fsop_handlereq(mp, parinode, hreq, &inode); | 344 | dentry = xfs_handlereq_to_dentry(parfilp, hreq); |
| 375 | if (error) | 345 | if (IS_ERR(dentry)) |
| 376 | return -error; | 346 | return PTR_ERR(dentry); |
| 377 | 347 | ||
| 378 | /* Restrict this handle operation to symlinks only. */ | 348 | /* Restrict this handle operation to symlinks only. */ |
| 379 | if (!S_ISLNK(inode->i_mode)) { | 349 | if (!S_ISLNK(dentry->d_inode->i_mode)) { |
| 380 | error = -XFS_ERROR(EINVAL); | 350 | error = -XFS_ERROR(EINVAL); |
| 381 | goto out_iput; | 351 | goto out_dput; |
| 382 | } | 352 | } |
| 383 | 353 | ||
| 384 | if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { | 354 | if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { |
| 385 | error = -XFS_ERROR(EFAULT); | 355 | error = -XFS_ERROR(EFAULT); |
| 386 | goto out_iput; | 356 | goto out_dput; |
| 387 | } | 357 | } |
| 388 | 358 | ||
| 389 | link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); | 359 | link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); |
| 390 | if (!link) | 360 | if (!link) { |
| 391 | goto out_iput; | 361 | error = -XFS_ERROR(ENOMEM); |
| 362 | goto out_dput; | ||
| 363 | } | ||
| 392 | 364 | ||
| 393 | error = -xfs_readlink(XFS_I(inode), link); | 365 | error = -xfs_readlink(XFS_I(dentry->d_inode), link); |
| 394 | if (error) | 366 | if (error) |
| 395 | goto out_kfree; | 367 | goto out_kfree; |
| 396 | error = do_readlink(hreq->ohandle, olen, link); | 368 | error = do_readlink(hreq->ohandle, olen, link); |
| @@ -399,32 +371,31 @@ xfs_readlink_by_handle( | |||
| 399 | 371 | ||
| 400 | out_kfree: | 372 | out_kfree: |
| 401 | kfree(link); | 373 | kfree(link); |
| 402 | out_iput: | 374 | out_dput: |
| 403 | iput(inode); | 375 | dput(dentry); |
| 404 | return error; | 376 | return error; |
| 405 | } | 377 | } |
| 406 | 378 | ||
| 407 | STATIC int | 379 | STATIC int |
| 408 | xfs_fssetdm_by_handle( | 380 | xfs_fssetdm_by_handle( |
| 409 | xfs_mount_t *mp, | 381 | struct file *parfilp, |
| 410 | void __user *arg, | 382 | void __user *arg) |
| 411 | struct inode *parinode) | ||
| 412 | { | 383 | { |
| 413 | int error; | 384 | int error; |
| 414 | struct fsdmidata fsd; | 385 | struct fsdmidata fsd; |
| 415 | xfs_fsop_setdm_handlereq_t dmhreq; | 386 | xfs_fsop_setdm_handlereq_t dmhreq; |
| 416 | struct inode *inode; | 387 | struct dentry *dentry; |
| 417 | 388 | ||
| 418 | if (!capable(CAP_MKNOD)) | 389 | if (!capable(CAP_MKNOD)) |
| 419 | return -XFS_ERROR(EPERM); | 390 | return -XFS_ERROR(EPERM); |
| 420 | if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) | 391 | if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) |
| 421 | return -XFS_ERROR(EFAULT); | 392 | return -XFS_ERROR(EFAULT); |
| 422 | 393 | ||
| 423 | error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &inode); | 394 | dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); |
| 424 | if (error) | 395 | if (IS_ERR(dentry)) |
| 425 | return -error; | 396 | return PTR_ERR(dentry); |
| 426 | 397 | ||
| 427 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { | 398 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { |
| 428 | error = -XFS_ERROR(EPERM); | 399 | error = -XFS_ERROR(EPERM); |
| 429 | goto out; | 400 | goto out; |
| 430 | } | 401 | } |
| @@ -434,24 +405,23 @@ xfs_fssetdm_by_handle( | |||
| 434 | goto out; | 405 | goto out; |
| 435 | } | 406 | } |
| 436 | 407 | ||
| 437 | error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask, | 408 | error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask, |
| 438 | fsd.fsd_dmstate); | 409 | fsd.fsd_dmstate); |
| 439 | 410 | ||
| 440 | out: | 411 | out: |
| 441 | iput(inode); | 412 | dput(dentry); |
| 442 | return error; | 413 | return error; |
| 443 | } | 414 | } |
| 444 | 415 | ||
| 445 | STATIC int | 416 | STATIC int |
| 446 | xfs_attrlist_by_handle( | 417 | xfs_attrlist_by_handle( |
| 447 | xfs_mount_t *mp, | 418 | struct file *parfilp, |
| 448 | void __user *arg, | 419 | void __user *arg) |
| 449 | struct inode *parinode) | ||
| 450 | { | 420 | { |
| 451 | int error; | 421 | int error = -ENOMEM; |
| 452 | attrlist_cursor_kern_t *cursor; | 422 | attrlist_cursor_kern_t *cursor; |
| 453 | xfs_fsop_attrlist_handlereq_t al_hreq; | 423 | xfs_fsop_attrlist_handlereq_t al_hreq; |
| 454 | struct inode *inode; | 424 | struct dentry *dentry; |
| 455 | char *kbuf; | 425 | char *kbuf; |
| 456 | 426 | ||
| 457 | if (!capable(CAP_SYS_ADMIN)) | 427 | if (!capable(CAP_SYS_ADMIN)) |
| @@ -467,16 +437,16 @@ xfs_attrlist_by_handle( | |||
| 467 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) | 437 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) |
| 468 | return -XFS_ERROR(EINVAL); | 438 | return -XFS_ERROR(EINVAL); |
| 469 | 439 | ||
| 470 | error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, &inode); | 440 | dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq); |
| 471 | if (error) | 441 | if (IS_ERR(dentry)) |
| 472 | goto out; | 442 | return PTR_ERR(dentry); |
| 473 | 443 | ||
| 474 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); | 444 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); |
| 475 | if (!kbuf) | 445 | if (!kbuf) |
| 476 | goto out_vn_rele; | 446 | goto out_dput; |
| 477 | 447 | ||
| 478 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; | 448 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; |
| 479 | error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen, | 449 | error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, |
| 480 | al_hreq.flags, cursor); | 450 | al_hreq.flags, cursor); |
| 481 | if (error) | 451 | if (error) |
| 482 | goto out_kfree; | 452 | goto out_kfree; |
| @@ -486,10 +456,9 @@ xfs_attrlist_by_handle( | |||
| 486 | 456 | ||
| 487 | out_kfree: | 457 | out_kfree: |
| 488 | kfree(kbuf); | 458 | kfree(kbuf); |
| 489 | out_vn_rele: | 459 | out_dput: |
| 490 | iput(inode); | 460 | dput(dentry); |
| 491 | out: | 461 | return error; |
| 492 | return -error; | ||
| 493 | } | 462 | } |
| 494 | 463 | ||
| 495 | int | 464 | int |
| @@ -564,15 +533,13 @@ xfs_attrmulti_attr_remove( | |||
| 564 | 533 | ||
| 565 | STATIC int | 534 | STATIC int |
| 566 | xfs_attrmulti_by_handle( | 535 | xfs_attrmulti_by_handle( |
| 567 | xfs_mount_t *mp, | ||
| 568 | void __user *arg, | ||
| 569 | struct file *parfilp, | 536 | struct file *parfilp, |
| 570 | struct inode *parinode) | 537 | void __user *arg) |
| 571 | { | 538 | { |
| 572 | int error; | 539 | int error; |
| 573 | xfs_attr_multiop_t *ops; | 540 | xfs_attr_multiop_t *ops; |
| 574 | xfs_fsop_attrmulti_handlereq_t am_hreq; | 541 | xfs_fsop_attrmulti_handlereq_t am_hreq; |
| 575 | struct inode *inode; | 542 | struct dentry *dentry; |
| 576 | unsigned int i, size; | 543 | unsigned int i, size; |
| 577 | char *attr_name; | 544 | char *attr_name; |
| 578 | 545 | ||
| @@ -581,19 +548,19 @@ xfs_attrmulti_by_handle( | |||
| 581 | if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t))) | 548 | if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t))) |
| 582 | return -XFS_ERROR(EFAULT); | 549 | return -XFS_ERROR(EFAULT); |
| 583 | 550 | ||
| 584 | error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &inode); | 551 | dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq); |
| 585 | if (error) | 552 | if (IS_ERR(dentry)) |
| 586 | goto out; | 553 | return PTR_ERR(dentry); |
| 587 | 554 | ||
| 588 | error = E2BIG; | 555 | error = E2BIG; |
| 589 | size = am_hreq.opcount * sizeof(xfs_attr_multiop_t); | 556 | size = am_hreq.opcount * sizeof(xfs_attr_multiop_t); |
| 590 | if (!size || size > 16 * PAGE_SIZE) | 557 | if (!size || size > 16 * PAGE_SIZE) |
| 591 | goto out_vn_rele; | 558 | goto out_dput; |
| 592 | 559 | ||
| 593 | error = ENOMEM; | 560 | error = ENOMEM; |
| 594 | ops = kmalloc(size, GFP_KERNEL); | 561 | ops = kmalloc(size, GFP_KERNEL); |
| 595 | if (!ops) | 562 | if (!ops) |
| 596 | goto out_vn_rele; | 563 | goto out_dput; |
| 597 | 564 | ||
| 598 | error = EFAULT; | 565 | error = EFAULT; |
| 599 | if (copy_from_user(ops, am_hreq.ops, size)) | 566 | if (copy_from_user(ops, am_hreq.ops, size)) |
| @@ -615,25 +582,28 @@ xfs_attrmulti_by_handle( | |||
| 615 | 582 | ||
| 616 | switch (ops[i].am_opcode) { | 583 | switch (ops[i].am_opcode) { |
| 617 | case ATTR_OP_GET: | 584 | case ATTR_OP_GET: |
| 618 | ops[i].am_error = xfs_attrmulti_attr_get(inode, | 585 | ops[i].am_error = xfs_attrmulti_attr_get( |
| 619 | attr_name, ops[i].am_attrvalue, | 586 | dentry->d_inode, attr_name, |
| 620 | &ops[i].am_length, ops[i].am_flags); | 587 | ops[i].am_attrvalue, &ops[i].am_length, |
| 588 | ops[i].am_flags); | ||
| 621 | break; | 589 | break; |
| 622 | case ATTR_OP_SET: | 590 | case ATTR_OP_SET: |
| 623 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | 591 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); |
| 624 | if (ops[i].am_error) | 592 | if (ops[i].am_error) |
| 625 | break; | 593 | break; |
| 626 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | 594 | ops[i].am_error = xfs_attrmulti_attr_set( |
| 627 | attr_name, ops[i].am_attrvalue, | 595 | dentry->d_inode, attr_name, |
| 628 | ops[i].am_length, ops[i].am_flags); | 596 | ops[i].am_attrvalue, ops[i].am_length, |
| 597 | ops[i].am_flags); | ||
| 629 | mnt_drop_write(parfilp->f_path.mnt); | 598 | mnt_drop_write(parfilp->f_path.mnt); |
| 630 | break; | 599 | break; |
| 631 | case ATTR_OP_REMOVE: | 600 | case ATTR_OP_REMOVE: |
| 632 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | 601 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); |
| 633 | if (ops[i].am_error) | 602 | if (ops[i].am_error) |
| 634 | break; | 603 | break; |
| 635 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | 604 | ops[i].am_error = xfs_attrmulti_attr_remove( |
| 636 | attr_name, ops[i].am_flags); | 605 | dentry->d_inode, attr_name, |
| 606 | ops[i].am_flags); | ||
| 637 | mnt_drop_write(parfilp->f_path.mnt); | 607 | mnt_drop_write(parfilp->f_path.mnt); |
| 638 | break; | 608 | break; |
| 639 | default: | 609 | default: |
| @@ -647,9 +617,8 @@ xfs_attrmulti_by_handle( | |||
| 647 | kfree(attr_name); | 617 | kfree(attr_name); |
| 648 | out_kfree_ops: | 618 | out_kfree_ops: |
| 649 | kfree(ops); | 619 | kfree(ops); |
| 650 | out_vn_rele: | 620 | out_dput: |
| 651 | iput(inode); | 621 | dput(dentry); |
| 652 | out: | ||
| 653 | return -error; | 622 | return -error; |
| 654 | } | 623 | } |
| 655 | 624 | ||
| @@ -1440,23 +1409,23 @@ xfs_file_ioctl( | |||
| 1440 | 1409 | ||
| 1441 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | 1410 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) |
| 1442 | return -XFS_ERROR(EFAULT); | 1411 | return -XFS_ERROR(EFAULT); |
| 1443 | return xfs_open_by_handle(mp, &hreq, filp, inode); | 1412 | return xfs_open_by_handle(filp, &hreq); |
| 1444 | } | 1413 | } |
| 1445 | case XFS_IOC_FSSETDM_BY_HANDLE: | 1414 | case XFS_IOC_FSSETDM_BY_HANDLE: |
| 1446 | return xfs_fssetdm_by_handle(mp, arg, inode); | 1415 | return xfs_fssetdm_by_handle(filp, arg); |
| 1447 | 1416 | ||
| 1448 | case XFS_IOC_READLINK_BY_HANDLE: { | 1417 | case XFS_IOC_READLINK_BY_HANDLE: { |
| 1449 | xfs_fsop_handlereq_t hreq; | 1418 | xfs_fsop_handlereq_t hreq; |
| 1450 | 1419 | ||
| 1451 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) | 1420 | if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) |
| 1452 | return -XFS_ERROR(EFAULT); | 1421 | return -XFS_ERROR(EFAULT); |
| 1453 | return xfs_readlink_by_handle(mp, &hreq, inode); | 1422 | return xfs_readlink_by_handle(filp, &hreq); |
| 1454 | } | 1423 | } |
| 1455 | case XFS_IOC_ATTRLIST_BY_HANDLE: | 1424 | case XFS_IOC_ATTRLIST_BY_HANDLE: |
| 1456 | return xfs_attrlist_by_handle(mp, arg, inode); | 1425 | return xfs_attrlist_by_handle(filp, arg); |
| 1457 | 1426 | ||
| 1458 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | 1427 | case XFS_IOC_ATTRMULTI_BY_HANDLE: |
| 1459 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); | 1428 | return xfs_attrmulti_by_handle(filp, arg); |
| 1460 | 1429 | ||
| 1461 | case XFS_IOC_SWAPEXT: { | 1430 | case XFS_IOC_SWAPEXT: { |
| 1462 | struct xfs_swapext sxp; | 1431 | struct xfs_swapext sxp; |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.h b/fs/xfs/linux-2.6/xfs_ioctl.h index 8c16bf2d7e03..7bd7c6afc1eb 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.h +++ b/fs/xfs/linux-2.6/xfs_ioctl.h | |||
| @@ -34,16 +34,13 @@ xfs_find_handle( | |||
| 34 | 34 | ||
| 35 | extern int | 35 | extern int |
| 36 | xfs_open_by_handle( | 36 | xfs_open_by_handle( |
| 37 | xfs_mount_t *mp, | ||
| 38 | xfs_fsop_handlereq_t *hreq, | ||
| 39 | struct file *parfilp, | 37 | struct file *parfilp, |
| 40 | struct inode *parinode); | 38 | xfs_fsop_handlereq_t *hreq); |
| 41 | 39 | ||
| 42 | extern int | 40 | extern int |
| 43 | xfs_readlink_by_handle( | 41 | xfs_readlink_by_handle( |
| 44 | xfs_mount_t *mp, | 42 | struct file *parfilp, |
| 45 | xfs_fsop_handlereq_t *hreq, | 43 | xfs_fsop_handlereq_t *hreq); |
| 46 | struct inode *parinode); | ||
| 47 | 44 | ||
| 48 | extern int | 45 | extern int |
| 49 | xfs_attrmulti_attr_get( | 46 | xfs_attrmulti_attr_get( |
| @@ -67,6 +64,12 @@ xfs_attrmulti_attr_remove( | |||
| 67 | char *name, | 64 | char *name, |
| 68 | __uint32_t flags); | 65 | __uint32_t flags); |
| 69 | 66 | ||
| 67 | extern struct dentry * | ||
| 68 | xfs_handle_to_dentry( | ||
| 69 | struct file *parfilp, | ||
| 70 | void __user *uhandle, | ||
| 71 | u32 hlen); | ||
| 72 | |||
| 70 | extern long | 73 | extern long |
| 71 | xfs_file_ioctl( | 74 | xfs_file_ioctl( |
| 72 | struct file *filp, | 75 | struct file *filp, |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 50903ad3182e..fd4362063f25 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
| @@ -340,96 +340,24 @@ xfs_compat_handlereq_copyin( | |||
| 340 | return 0; | 340 | return 0; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| 343 | /* | 343 | STATIC struct dentry * |
| 344 | * Convert userspace handle data into inode. | 344 | xfs_compat_handlereq_to_dentry( |
| 345 | * | 345 | struct file *parfilp, |
| 346 | * We use the fact that all the fsop_handlereq ioctl calls have a data | 346 | compat_xfs_fsop_handlereq_t *hreq) |
| 347 | * structure argument whose first component is always a xfs_fsop_handlereq_t, | ||
| 348 | * so we can pass that sub structure into this handy, shared routine. | ||
| 349 | * | ||
| 350 | * If no error, caller must always iput the returned inode. | ||
| 351 | */ | ||
| 352 | STATIC int | ||
| 353 | xfs_vget_fsop_handlereq_compat( | ||
| 354 | xfs_mount_t *mp, | ||
| 355 | struct inode *parinode, /* parent inode pointer */ | ||
| 356 | compat_xfs_fsop_handlereq_t *hreq, | ||
| 357 | struct inode **inode) | ||
| 358 | { | 347 | { |
| 359 | void __user *hanp; | 348 | return xfs_handle_to_dentry(parfilp, |
| 360 | size_t hlen; | 349 | compat_ptr(hreq->ihandle), hreq->ihandlen); |
| 361 | xfs_fid_t *xfid; | ||
| 362 | xfs_handle_t *handlep; | ||
| 363 | xfs_handle_t handle; | ||
| 364 | xfs_inode_t *ip; | ||
| 365 | xfs_ino_t ino; | ||
| 366 | __u32 igen; | ||
| 367 | int error; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Only allow handle opens under a directory. | ||
| 371 | */ | ||
| 372 | if (!S_ISDIR(parinode->i_mode)) | ||
| 373 | return XFS_ERROR(ENOTDIR); | ||
| 374 | |||
| 375 | hanp = compat_ptr(hreq->ihandle); | ||
| 376 | hlen = hreq->ihandlen; | ||
| 377 | handlep = &handle; | ||
| 378 | |||
| 379 | if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) | ||
| 380 | return XFS_ERROR(EINVAL); | ||
| 381 | if (copy_from_user(handlep, hanp, hlen)) | ||
| 382 | return XFS_ERROR(EFAULT); | ||
| 383 | if (hlen < sizeof(*handlep)) | ||
| 384 | memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); | ||
| 385 | if (hlen > sizeof(handlep->ha_fsid)) { | ||
| 386 | if (handlep->ha_fid.fid_len != | ||
| 387 | (hlen - sizeof(handlep->ha_fsid) - | ||
| 388 | sizeof(handlep->ha_fid.fid_len)) || | ||
| 389 | handlep->ha_fid.fid_pad) | ||
| 390 | return XFS_ERROR(EINVAL); | ||
| 391 | } | ||
| 392 | |||
| 393 | /* | ||
| 394 | * Crack the handle, obtain the inode # & generation # | ||
| 395 | */ | ||
| 396 | xfid = (struct xfs_fid *)&handlep->ha_fid; | ||
| 397 | if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) { | ||
| 398 | ino = xfid->fid_ino; | ||
| 399 | igen = xfid->fid_gen; | ||
| 400 | } else { | ||
| 401 | return XFS_ERROR(EINVAL); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* | ||
| 405 | * Get the XFS inode, building a Linux inode to go with it. | ||
| 406 | */ | ||
| 407 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0); | ||
| 408 | if (error) | ||
| 409 | return error; | ||
| 410 | if (ip == NULL) | ||
| 411 | return XFS_ERROR(EIO); | ||
| 412 | if (ip->i_d.di_gen != igen) { | ||
| 413 | xfs_iput_new(ip, XFS_ILOCK_SHARED); | ||
| 414 | return XFS_ERROR(ENOENT); | ||
| 415 | } | ||
| 416 | |||
| 417 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
| 418 | |||
| 419 | *inode = VFS_I(ip); | ||
| 420 | return 0; | ||
| 421 | } | 350 | } |
| 422 | 351 | ||
| 423 | STATIC int | 352 | STATIC int |
| 424 | xfs_compat_attrlist_by_handle( | 353 | xfs_compat_attrlist_by_handle( |
| 425 | xfs_mount_t *mp, | 354 | struct file *parfilp, |
| 426 | void __user *arg, | 355 | void __user *arg) |
| 427 | struct inode *parinode) | ||
| 428 | { | 356 | { |
| 429 | int error; | 357 | int error; |
| 430 | attrlist_cursor_kern_t *cursor; | 358 | attrlist_cursor_kern_t *cursor; |
| 431 | compat_xfs_fsop_attrlist_handlereq_t al_hreq; | 359 | compat_xfs_fsop_attrlist_handlereq_t al_hreq; |
| 432 | struct inode *inode; | 360 | struct dentry *dentry; |
| 433 | char *kbuf; | 361 | char *kbuf; |
| 434 | 362 | ||
| 435 | if (!capable(CAP_SYS_ADMIN)) | 363 | if (!capable(CAP_SYS_ADMIN)) |
| @@ -446,17 +374,17 @@ xfs_compat_attrlist_by_handle( | |||
| 446 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) | 374 | if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE)) |
| 447 | return -XFS_ERROR(EINVAL); | 375 | return -XFS_ERROR(EINVAL); |
| 448 | 376 | ||
| 449 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &al_hreq.hreq, | 377 | dentry = xfs_compat_handlereq_to_dentry(parfilp, &al_hreq.hreq); |
| 450 | &inode); | 378 | if (IS_ERR(dentry)) |
| 451 | if (error) | 379 | return PTR_ERR(dentry); |
| 452 | goto out; | ||
| 453 | 380 | ||
| 381 | error = -ENOMEM; | ||
| 454 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); | 382 | kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); |
| 455 | if (!kbuf) | 383 | if (!kbuf) |
| 456 | goto out_vn_rele; | 384 | goto out_dput; |
| 457 | 385 | ||
| 458 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; | 386 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; |
| 459 | error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen, | 387 | error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, |
| 460 | al_hreq.flags, cursor); | 388 | al_hreq.flags, cursor); |
| 461 | if (error) | 389 | if (error) |
| 462 | goto out_kfree; | 390 | goto out_kfree; |
| @@ -466,22 +394,20 @@ xfs_compat_attrlist_by_handle( | |||
| 466 | 394 | ||
| 467 | out_kfree: | 395 | out_kfree: |
| 468 | kfree(kbuf); | 396 | kfree(kbuf); |
| 469 | out_vn_rele: | 397 | out_dput: |
| 470 | iput(inode); | 398 | dput(dentry); |
| 471 | out: | 399 | return error; |
| 472 | return -error; | ||
| 473 | } | 400 | } |
| 474 | 401 | ||
| 475 | STATIC int | 402 | STATIC int |
| 476 | xfs_compat_attrmulti_by_handle( | 403 | xfs_compat_attrmulti_by_handle( |
| 477 | xfs_mount_t *mp, | 404 | struct file *parfilp, |
| 478 | void __user *arg, | 405 | void __user *arg) |
| 479 | struct inode *parinode) | ||
| 480 | { | 406 | { |
| 481 | int error; | 407 | int error; |
| 482 | compat_xfs_attr_multiop_t *ops; | 408 | compat_xfs_attr_multiop_t *ops; |
| 483 | compat_xfs_fsop_attrmulti_handlereq_t am_hreq; | 409 | compat_xfs_fsop_attrmulti_handlereq_t am_hreq; |
| 484 | struct inode *inode; | 410 | struct dentry *dentry; |
| 485 | unsigned int i, size; | 411 | unsigned int i, size; |
| 486 | char *attr_name; | 412 | char *attr_name; |
| 487 | 413 | ||
| @@ -491,20 +417,19 @@ xfs_compat_attrmulti_by_handle( | |||
| 491 | sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) | 417 | sizeof(compat_xfs_fsop_attrmulti_handlereq_t))) |
| 492 | return -XFS_ERROR(EFAULT); | 418 | return -XFS_ERROR(EFAULT); |
| 493 | 419 | ||
| 494 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &am_hreq.hreq, | 420 | dentry = xfs_compat_handlereq_to_dentry(parfilp, &am_hreq.hreq); |
| 495 | &inode); | 421 | if (IS_ERR(dentry)) |
| 496 | if (error) | 422 | return PTR_ERR(dentry); |
| 497 | goto out; | ||
| 498 | 423 | ||
| 499 | error = E2BIG; | 424 | error = E2BIG; |
| 500 | size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); | 425 | size = am_hreq.opcount * sizeof(compat_xfs_attr_multiop_t); |
| 501 | if (!size || size > 16 * PAGE_SIZE) | 426 | if (!size || size > 16 * PAGE_SIZE) |
| 502 | goto out_vn_rele; | 427 | goto out_dput; |
| 503 | 428 | ||
| 504 | error = ENOMEM; | 429 | error = ENOMEM; |
| 505 | ops = kmalloc(size, GFP_KERNEL); | 430 | ops = kmalloc(size, GFP_KERNEL); |
| 506 | if (!ops) | 431 | if (!ops) |
| 507 | goto out_vn_rele; | 432 | goto out_dput; |
| 508 | 433 | ||
| 509 | error = EFAULT; | 434 | error = EFAULT; |
| 510 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) | 435 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) |
| @@ -527,20 +452,21 @@ xfs_compat_attrmulti_by_handle( | |||
| 527 | 452 | ||
| 528 | switch (ops[i].am_opcode) { | 453 | switch (ops[i].am_opcode) { |
| 529 | case ATTR_OP_GET: | 454 | case ATTR_OP_GET: |
| 530 | ops[i].am_error = xfs_attrmulti_attr_get(inode, | 455 | ops[i].am_error = xfs_attrmulti_attr_get( |
| 531 | attr_name, | 456 | dentry->d_inode, attr_name, |
| 532 | compat_ptr(ops[i].am_attrvalue), | 457 | compat_ptr(ops[i].am_attrvalue), |
| 533 | &ops[i].am_length, ops[i].am_flags); | 458 | &ops[i].am_length, ops[i].am_flags); |
| 534 | break; | 459 | break; |
| 535 | case ATTR_OP_SET: | 460 | case ATTR_OP_SET: |
| 536 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | 461 | ops[i].am_error = xfs_attrmulti_attr_set( |
| 537 | attr_name, | 462 | dentry->d_inode, attr_name, |
| 538 | compat_ptr(ops[i].am_attrvalue), | 463 | compat_ptr(ops[i].am_attrvalue), |
| 539 | ops[i].am_length, ops[i].am_flags); | 464 | ops[i].am_length, ops[i].am_flags); |
| 540 | break; | 465 | break; |
| 541 | case ATTR_OP_REMOVE: | 466 | case ATTR_OP_REMOVE: |
| 542 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | 467 | ops[i].am_error = xfs_attrmulti_attr_remove( |
| 543 | attr_name, ops[i].am_flags); | 468 | dentry->d_inode, attr_name, |
| 469 | ops[i].am_flags); | ||
| 544 | break; | 470 | break; |
| 545 | default: | 471 | default: |
| 546 | ops[i].am_error = EINVAL; | 472 | ops[i].am_error = EINVAL; |
| @@ -553,22 +479,20 @@ xfs_compat_attrmulti_by_handle( | |||
| 553 | kfree(attr_name); | 479 | kfree(attr_name); |
| 554 | out_kfree_ops: | 480 | out_kfree_ops: |
| 555 | kfree(ops); | 481 | kfree(ops); |
| 556 | out_vn_rele: | 482 | out_dput: |
| 557 | iput(inode); | 483 | dput(dentry); |
| 558 | out: | ||
| 559 | return -error; | 484 | return -error; |
| 560 | } | 485 | } |
| 561 | 486 | ||
| 562 | STATIC int | 487 | STATIC int |
| 563 | xfs_compat_fssetdm_by_handle( | 488 | xfs_compat_fssetdm_by_handle( |
| 564 | xfs_mount_t *mp, | 489 | struct file *parfilp, |
| 565 | void __user *arg, | 490 | void __user *arg) |
| 566 | struct inode *parinode) | ||
| 567 | { | 491 | { |
| 568 | int error; | 492 | int error; |
| 569 | struct fsdmidata fsd; | 493 | struct fsdmidata fsd; |
| 570 | compat_xfs_fsop_setdm_handlereq_t dmhreq; | 494 | compat_xfs_fsop_setdm_handlereq_t dmhreq; |
| 571 | struct inode *inode; | 495 | struct dentry *dentry; |
| 572 | 496 | ||
| 573 | if (!capable(CAP_MKNOD)) | 497 | if (!capable(CAP_MKNOD)) |
| 574 | return -XFS_ERROR(EPERM); | 498 | return -XFS_ERROR(EPERM); |
| @@ -576,12 +500,11 @@ xfs_compat_fssetdm_by_handle( | |||
| 576 | sizeof(compat_xfs_fsop_setdm_handlereq_t))) | 500 | sizeof(compat_xfs_fsop_setdm_handlereq_t))) |
| 577 | return -XFS_ERROR(EFAULT); | 501 | return -XFS_ERROR(EFAULT); |
| 578 | 502 | ||
| 579 | error = xfs_vget_fsop_handlereq_compat(mp, parinode, &dmhreq.hreq, | 503 | dentry = xfs_compat_handlereq_to_dentry(parfilp, &dmhreq.hreq); |
| 580 | &inode); | 504 | if (IS_ERR(dentry)) |
| 581 | if (error) | 505 | return PTR_ERR(dentry); |
| 582 | return -error; | ||
| 583 | 506 | ||
| 584 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { | 507 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { |
| 585 | error = -XFS_ERROR(EPERM); | 508 | error = -XFS_ERROR(EPERM); |
| 586 | goto out; | 509 | goto out; |
| 587 | } | 510 | } |
| @@ -591,11 +514,11 @@ xfs_compat_fssetdm_by_handle( | |||
| 591 | goto out; | 514 | goto out; |
| 592 | } | 515 | } |
| 593 | 516 | ||
| 594 | error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask, | 517 | error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask, |
| 595 | fsd.fsd_dmstate); | 518 | fsd.fsd_dmstate); |
| 596 | 519 | ||
| 597 | out: | 520 | out: |
| 598 | iput(inode); | 521 | dput(dentry); |
| 599 | return error; | 522 | return error; |
| 600 | } | 523 | } |
| 601 | 524 | ||
| @@ -722,21 +645,21 @@ xfs_file_compat_ioctl( | |||
| 722 | 645 | ||
| 723 | if (xfs_compat_handlereq_copyin(&hreq, arg)) | 646 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
| 724 | return -XFS_ERROR(EFAULT); | 647 | return -XFS_ERROR(EFAULT); |
| 725 | return xfs_open_by_handle(mp, &hreq, filp, inode); | 648 | return xfs_open_by_handle(filp, &hreq); |
| 726 | } | 649 | } |
| 727 | case XFS_IOC_READLINK_BY_HANDLE_32: { | 650 | case XFS_IOC_READLINK_BY_HANDLE_32: { |
| 728 | struct xfs_fsop_handlereq hreq; | 651 | struct xfs_fsop_handlereq hreq; |
| 729 | 652 | ||
| 730 | if (xfs_compat_handlereq_copyin(&hreq, arg)) | 653 | if (xfs_compat_handlereq_copyin(&hreq, arg)) |
| 731 | return -XFS_ERROR(EFAULT); | 654 | return -XFS_ERROR(EFAULT); |
| 732 | return xfs_readlink_by_handle(mp, &hreq, inode); | 655 | return xfs_readlink_by_handle(filp, &hreq); |
| 733 | } | 656 | } |
| 734 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: | 657 | case XFS_IOC_ATTRLIST_BY_HANDLE_32: |
| 735 | return xfs_compat_attrlist_by_handle(mp, arg, inode); | 658 | return xfs_compat_attrlist_by_handle(filp, arg); |
| 736 | case XFS_IOC_ATTRMULTI_BY_HANDLE_32: | 659 | case XFS_IOC_ATTRMULTI_BY_HANDLE_32: |
| 737 | return xfs_compat_attrmulti_by_handle(mp, arg, inode); | 660 | return xfs_compat_attrmulti_by_handle(filp, arg); |
| 738 | case XFS_IOC_FSSETDM_BY_HANDLE_32: | 661 | case XFS_IOC_FSSETDM_BY_HANDLE_32: |
| 739 | return xfs_compat_fssetdm_by_handle(mp, arg, inode); | 662 | return xfs_compat_fssetdm_by_handle(filp, arg); |
| 740 | default: | 663 | default: |
| 741 | return -XFS_ERROR(ENOIOCTLCMD); | 664 | return -XFS_ERROR(ENOIOCTLCMD); |
| 742 | } | 665 | } |
