~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/xfs_ioctl.c

Version: ~ [ linux-5.11 ] ~ [ linux-5.10.17 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.99 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.176 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.221 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.257 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.257 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  3  * All Rights Reserved.
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation.
  8  *
  9  * This program is distributed in the hope that it would be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write the Free Software Foundation,
 16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17  */
 18 #include "xfs.h"
 19 #include "xfs_fs.h"
 20 #include "xfs_shared.h"
 21 #include "xfs_format.h"
 22 #include "xfs_log_format.h"
 23 #include "xfs_trans_resv.h"
 24 #include "xfs_sb.h"
 25 #include "xfs_ag.h"
 26 #include "xfs_mount.h"
 27 #include "xfs_inode.h"
 28 #include "xfs_ioctl.h"
 29 #include "xfs_alloc.h"
 30 #include "xfs_rtalloc.h"
 31 #include "xfs_itable.h"
 32 #include "xfs_error.h"
 33 #include "xfs_attr.h"
 34 #include "xfs_bmap.h"
 35 #include "xfs_bmap_util.h"
 36 #include "xfs_fsops.h"
 37 #include "xfs_discard.h"
 38 #include "xfs_quota.h"
 39 #include "xfs_export.h"
 40 #include "xfs_trace.h"
 41 #include "xfs_icache.h"
 42 #include "xfs_symlink.h"
 43 #include "xfs_dinode.h"
 44 #include "xfs_trans.h"
 45 
 46 #include <linux/capability.h>
 47 #include <linux/dcache.h>
 48 #include <linux/mount.h>
 49 #include <linux/namei.h>
 50 #include <linux/pagemap.h>
 51 #include <linux/slab.h>
 52 #include <linux/exportfs.h>
 53 
 54 /*
 55  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
 56  * a file or fs handle.
 57  *
 58  * XFS_IOC_PATH_TO_FSHANDLE
 59  *    returns fs handle for a mount point or path within that mount point
 60  * XFS_IOC_FD_TO_HANDLE
 61  *    returns full handle for a FD opened in user space
 62  * XFS_IOC_PATH_TO_HANDLE
 63  *    returns full handle for a path
 64  */
 65 int
 66 xfs_find_handle(
 67         unsigned int            cmd,
 68         xfs_fsop_handlereq_t    *hreq)
 69 {
 70         int                     hsize;
 71         xfs_handle_t            handle;
 72         struct inode            *inode;
 73         struct fd               f = {NULL};
 74         struct path             path;
 75         int                     error;
 76         struct xfs_inode        *ip;
 77 
 78         if (cmd == XFS_IOC_FD_TO_HANDLE) {
 79                 f = fdget(hreq->fd);
 80                 if (!f.file)
 81                         return -EBADF;
 82                 inode = file_inode(f.file);
 83         } else {
 84                 error = user_lpath((const char __user *)hreq->path, &path);
 85                 if (error)
 86                         return error;
 87                 inode = path.dentry->d_inode;
 88         }
 89         ip = XFS_I(inode);
 90 
 91         /*
 92          * We can only generate handles for inodes residing on a XFS filesystem,
 93          * and only for regular files, directories or symbolic links.
 94          */
 95         error = -EINVAL;
 96         if (inode->i_sb->s_magic != XFS_SB_MAGIC)
 97                 goto out_put;
 98 
 99         error = -EBADF;
100         if (!S_ISREG(inode->i_mode) &&
101             !S_ISDIR(inode->i_mode) &&
102             !S_ISLNK(inode->i_mode))
103                 goto out_put;
104 
105 
106         memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
107 
108         if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
109                 /*
110                  * This handle only contains an fsid, zero the rest.
111                  */
112                 memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
113                 hsize = sizeof(xfs_fsid_t);
114         } else {
115                 handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
116                                         sizeof(handle.ha_fid.fid_len);
117                 handle.ha_fid.fid_pad = 0;
118                 handle.ha_fid.fid_gen = ip->i_d.di_gen;
119                 handle.ha_fid.fid_ino = ip->i_ino;
120 
121                 hsize = XFS_HSIZE(handle);
122         }
123 
124         error = -EFAULT;
125         if (copy_to_user(hreq->ohandle, &handle, hsize) ||
126             copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
127                 goto out_put;
128 
129         error = 0;
130 
131  out_put:
132         if (cmd == XFS_IOC_FD_TO_HANDLE)
133                 fdput(f);
134         else
135                 path_put(&path);
136         return error;
137 }
138 
139 /*
140  * No need to do permission checks on the various pathname components
141  * as the handle operations are privileged.
142  */
143 STATIC int
144 xfs_handle_acceptable(
145         void                    *context,
146         struct dentry           *dentry)
147 {
148         return 1;
149 }
150 
151 /*
152  * Convert userspace handle data into a dentry.
153  */
154 struct dentry *
155 xfs_handle_to_dentry(
156         struct file             *parfilp,
157         void __user             *uhandle,
158         u32                     hlen)
159 {
160         xfs_handle_t            handle;
161         struct xfs_fid64        fid;
162 
163         /*
164          * Only allow handle opens under a directory.
165          */
166         if (!S_ISDIR(file_inode(parfilp)->i_mode))
167                 return ERR_PTR(-ENOTDIR);
168 
169         if (hlen != sizeof(xfs_handle_t))
170                 return ERR_PTR(-EINVAL);
171         if (copy_from_user(&handle, uhandle, hlen))
172                 return ERR_PTR(-EFAULT);
173         if (handle.ha_fid.fid_len !=
174             sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
175                 return ERR_PTR(-EINVAL);
176 
177         memset(&fid, 0, sizeof(struct fid));
178         fid.ino = handle.ha_fid.fid_ino;
179         fid.gen = handle.ha_fid.fid_gen;
180 
181         return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
182                         FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
183                         xfs_handle_acceptable, NULL);
184 }
185 
186 STATIC struct dentry *
187 xfs_handlereq_to_dentry(
188         struct file             *parfilp,
189         xfs_fsop_handlereq_t    *hreq)
190 {
191         return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
192 }
193 
194 int
195 xfs_open_by_handle(
196         struct file             *parfilp,
197         xfs_fsop_handlereq_t    *hreq)
198 {
199         const struct cred       *cred = current_cred();
200         int                     error;
201         int                     fd;
202         int                     permflag;
203         struct file             *filp;
204         struct inode            *inode;
205         struct dentry           *dentry;
206         fmode_t                 fmode;
207         struct path             path;
208 
209         if (!capable(CAP_SYS_ADMIN))
210                 return -XFS_ERROR(EPERM);
211 
212         dentry = xfs_handlereq_to_dentry(parfilp, hreq);
213         if (IS_ERR(dentry))
214                 return PTR_ERR(dentry);
215         inode = dentry->d_inode;
216 
217         /* Restrict xfs_open_by_handle to directories & regular files. */
218         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
219                 error = -XFS_ERROR(EPERM);
220                 goto out_dput;
221         }
222 
223 #if BITS_PER_LONG != 32
224         hreq->oflags |= O_LARGEFILE;
225 #endif
226 
227         permflag = hreq->oflags;
228         fmode = OPEN_FMODE(permflag);
229         if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
230             (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
231                 error = -XFS_ERROR(EPERM);
232                 goto out_dput;
233         }
234 
235         if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
236                 error = -XFS_ERROR(EACCES);
237                 goto out_dput;
238         }
239 
240         /* Can't write directories. */
241         if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
242                 error = -XFS_ERROR(EISDIR);
243                 goto out_dput;
244         }
245 
246         fd = get_unused_fd_flags(0);
247         if (fd < 0) {
248                 error = fd;
249                 goto out_dput;
250         }
251 
252         path.mnt = parfilp->f_path.mnt;
253         path.dentry = dentry;
254         filp = dentry_open(&path, hreq->oflags, cred);
255         dput(dentry);
256         if (IS_ERR(filp)) {
257                 put_unused_fd(fd);
258                 return PTR_ERR(filp);
259         }
260 
261         if (S_ISREG(inode->i_mode)) {
262                 filp->f_flags |= O_NOATIME;
263                 filp->f_mode |= FMODE_NOCMTIME;
264         }
265 
266         fd_install(fd, filp);
267         return fd;
268 
269  out_dput:
270         dput(dentry);
271         return error;
272 }
273 
274 int
275 xfs_readlink_by_handle(
276         struct file             *parfilp,
277         xfs_fsop_handlereq_t    *hreq)
278 {
279         struct dentry           *dentry;
280         __u32                   olen;
281         void                    *link;
282         int                     error;
283 
284         if (!capable(CAP_SYS_ADMIN))
285                 return -XFS_ERROR(EPERM);
286 
287         dentry = xfs_handlereq_to_dentry(parfilp, hreq);
288         if (IS_ERR(dentry))
289                 return PTR_ERR(dentry);
290 
291         /* Restrict this handle operation to symlinks only. */
292         if (!S_ISLNK(dentry->d_inode->i_mode)) {
293                 error = -XFS_ERROR(EINVAL);
294                 goto out_dput;
295         }
296 
297         if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
298                 error = -XFS_ERROR(EFAULT);
299                 goto out_dput;
300         }
301 
302         link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
303         if (!link) {
304                 error = -XFS_ERROR(ENOMEM);
305                 goto out_dput;
306         }
307 
308         error = -xfs_readlink(XFS_I(dentry->d_inode), link);
309         if (error)
310                 goto out_kfree;
311         error = readlink_copy(hreq->ohandle, olen, link);
312         if (error)
313                 goto out_kfree;
314 
315  out_kfree:
316         kfree(link);
317  out_dput:
318         dput(dentry);
319         return error;
320 }
321 
322 int
323 xfs_set_dmattrs(
324         xfs_inode_t     *ip,
325         u_int           evmask,
326         u_int16_t       state)
327 {
328         xfs_mount_t     *mp = ip->i_mount;
329         xfs_trans_t     *tp;
330         int             error;
331 
332         if (!capable(CAP_SYS_ADMIN))
333                 return XFS_ERROR(EPERM);
334 
335         if (XFS_FORCED_SHUTDOWN(mp))
336                 return XFS_ERROR(EIO);
337 
338         tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS);
339         error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
340         if (error) {
341                 xfs_trans_cancel(tp, 0);
342                 return error;
343         }
344         xfs_ilock(ip, XFS_ILOCK_EXCL);
345         xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
346 
347         ip->i_d.di_dmevmask = evmask;
348         ip->i_d.di_dmstate  = state;
349 
350         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
351         error = xfs_trans_commit(tp, 0);
352 
353         return error;
354 }
355 
356 STATIC int
357 xfs_fssetdm_by_handle(
358         struct file             *parfilp,
359         void                    __user *arg)
360 {
361         int                     error;
362         struct fsdmidata        fsd;
363         xfs_fsop_setdm_handlereq_t dmhreq;
364         struct dentry           *dentry;
365 
366         if (!capable(CAP_MKNOD))
367                 return -XFS_ERROR(EPERM);
368         if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
369                 return -XFS_ERROR(EFAULT);
370 
371         error = mnt_want_write_file(parfilp);
372         if (error)
373                 return error;
374 
375         dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq);
376         if (IS_ERR(dentry)) {
377                 mnt_drop_write_file(parfilp);
378                 return PTR_ERR(dentry);
379         }
380 
381         if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
382                 error = -XFS_ERROR(EPERM);
383                 goto out;
384         }
385 
386         if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
387                 error = -XFS_ERROR(EFAULT);
388                 goto out;
389         }
390 
391         error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask,
392                                  fsd.fsd_dmstate);
393 
394  out:
395         mnt_drop_write_file(parfilp);
396         dput(dentry);
397         return error;
398 }
399 
400 STATIC int
401 xfs_attrlist_by_handle(
402         struct file             *parfilp,
403         void                    __user *arg)
404 {
405         int                     error = -ENOMEM;
406         attrlist_cursor_kern_t  *cursor;
407         xfs_fsop_attrlist_handlereq_t al_hreq;
408         struct dentry           *dentry;
409         char                    *kbuf;
410 
411         if (!capable(CAP_SYS_ADMIN))
412                 return -XFS_ERROR(EPERM);
413         if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
414                 return -XFS_ERROR(EFAULT);
415         if (al_hreq.buflen < sizeof(struct attrlist) ||
416             al_hreq.buflen > XATTR_LIST_MAX)
417                 return -XFS_ERROR(EINVAL);
418 
419         /*
420          * Reject flags, only allow namespaces.
421          */
422         if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
423                 return -XFS_ERROR(EINVAL);
424 
425         dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
426         if (IS_ERR(dentry))
427                 return PTR_ERR(dentry);
428 
429         kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
430         if (!kbuf)
431                 goto out_dput;
432 
433         cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
434         error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
435                                         al_hreq.flags, cursor);
436         if (error)
437                 goto out_kfree;
438 
439         if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
440                 error = -EFAULT;
441 
442 out_kfree:
443         kmem_free(kbuf);
444 out_dput:
445         dput(dentry);
446         return error;
447 }
448 
449 int
450 xfs_attrmulti_attr_get(
451         struct inode            *inode,
452         unsigned char           *name,
453         unsigned char           __user *ubuf,
454         __uint32_t              *len,
455         __uint32_t              flags)
456 {
457         unsigned char           *kbuf;
458         int                     error = EFAULT;
459 
460         if (*len > XATTR_SIZE_MAX)
461                 return EINVAL;
462         kbuf = kmem_zalloc_large(*len, KM_SLEEP);
463         if (!kbuf)
464                 return ENOMEM;
465 
466         error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
467         if (error)
468                 goto out_kfree;
469 
470         if (copy_to_user(ubuf, kbuf, *len))
471                 error = EFAULT;
472 
473 out_kfree:
474         kmem_free(kbuf);
475         return error;
476 }
477 
478 int
479 xfs_attrmulti_attr_set(
480         struct inode            *inode,
481         unsigned char           *name,
482         const unsigned char     __user *ubuf,
483         __uint32_t              len,
484         __uint32_t              flags)
485 {
486         unsigned char           *kbuf;
487         int                     error = EFAULT;
488 
489         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
490                 return EPERM;
491         if (len > XATTR_SIZE_MAX)
492                 return EINVAL;
493 
494         kbuf = memdup_user(ubuf, len);
495         if (IS_ERR(kbuf))
496                 return PTR_ERR(kbuf);
497 
498         error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
499 
500         return error;
501 }
502 
503 int
504 xfs_attrmulti_attr_remove(
505         struct inode            *inode,
506         unsigned char           *name,
507         __uint32_t              flags)
508 {
509         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
510                 return EPERM;
511         return xfs_attr_remove(XFS_I(inode), name, flags);
512 }
513 
514 STATIC int
515 xfs_attrmulti_by_handle(
516         struct file             *parfilp,
517         void                    __user *arg)
518 {
519         int                     error;
520         xfs_attr_multiop_t      *ops;
521         xfs_fsop_attrmulti_handlereq_t am_hreq;
522         struct dentry           *dentry;
523         unsigned int            i, size;
524         unsigned char           *attr_name;
525 
526         if (!capable(CAP_SYS_ADMIN))
527                 return -XFS_ERROR(EPERM);
528         if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
529                 return -XFS_ERROR(EFAULT);
530 
531         /* overflow check */
532         if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
533                 return -E2BIG;
534 
535         dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
536         if (IS_ERR(dentry))
537                 return PTR_ERR(dentry);
538 
539         error = E2BIG;
540         size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
541         if (!size || size > 16 * PAGE_SIZE)
542                 goto out_dput;
543 
544         ops = memdup_user(am_hreq.ops, size);
545         if (IS_ERR(ops)) {
546                 error = PTR_ERR(ops);
547                 goto out_dput;
548         }
549 
550         attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
551         if (!attr_name)
552                 goto out_kfree_ops;
553 
554         error = 0;
555         for (i = 0; i < am_hreq.opcount; i++) {
556                 ops[i].am_error = strncpy_from_user((char *)attr_name,
557                                 ops[i].am_attrname, MAXNAMELEN);
558                 if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
559                         error = -ERANGE;
560                 if (ops[i].am_error < 0)
561                         break;
562 
563                 switch (ops[i].am_opcode) {
564                 case ATTR_OP_GET:
565                         ops[i].am_error = xfs_attrmulti_attr_get(
566                                         dentry->d_inode, attr_name,
567                                         ops[i].am_attrvalue, &ops[i].am_length,
568                                         ops[i].am_flags);
569                         break;
570                 case ATTR_OP_SET:
571                         ops[i].am_error = mnt_want_write_file(parfilp);
572                         if (ops[i].am_error)
573                                 break;
574                         ops[i].am_error = xfs_attrmulti_attr_set(
575                                         dentry->d_inode, attr_name,
576                                         ops[i].am_attrvalue, ops[i].am_length,
577                                         ops[i].am_flags);
578                         mnt_drop_write_file(parfilp);
579                         break;
580                 case ATTR_OP_REMOVE:
581                         ops[i].am_error = mnt_want_write_file(parfilp);
582                         if (ops[i].am_error)
583                                 break;
584                         ops[i].am_error = xfs_attrmulti_attr_remove(
585                                         dentry->d_inode, attr_name,
586                                         ops[i].am_flags);
587                         mnt_drop_write_file(parfilp);
588                         break;
589                 default:
590                         ops[i].am_error = EINVAL;
591                 }
592         }
593 
594         if (copy_to_user(am_hreq.ops, ops, size))
595                 error = XFS_ERROR(EFAULT);
596 
597         kfree(attr_name);
598  out_kfree_ops:
599         kfree(ops);
600  out_dput:
601         dput(dentry);
602         return -error;
603 }
604 
605 int
606 xfs_ioc_space(
607         struct xfs_inode        *ip,
608         struct inode            *inode,
609         struct file             *filp,
610         int                     ioflags,
611         unsigned int            cmd,
612         xfs_flock64_t           *bf)
613 {
614         struct xfs_mount        *mp = ip->i_mount;
615         struct xfs_trans        *tp;
616         struct iattr            iattr;
617         bool                    setprealloc = false;
618         bool                    clrprealloc = false;
619         int                     error;
620 
621         /*
622          * Only allow the sys admin to reserve space unless
623          * unwritten extents are enabled.
624          */
625         if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
626             !capable(CAP_SYS_ADMIN))
627                 return -XFS_ERROR(EPERM);
628 
629         if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
630                 return -XFS_ERROR(EPERM);
631 
632         if (!(filp->f_mode & FMODE_WRITE))
633                 return -XFS_ERROR(EBADF);
634 
635         if (!S_ISREG(inode->i_mode))
636                 return -XFS_ERROR(EINVAL);
637 
638         error = mnt_want_write_file(filp);
639         if (error)
640                 return error;
641 
642         xfs_ilock(ip, XFS_IOLOCK_EXCL);
643 
644         switch (bf->l_whence) {
645         case 0: /*SEEK_SET*/
646                 break;
647         case 1: /*SEEK_CUR*/
648                 bf->l_start += filp->f_pos;
649                 break;
650         case 2: /*SEEK_END*/
651                 bf->l_start += XFS_ISIZE(ip);
652                 break;
653         default:
654                 error = XFS_ERROR(EINVAL);
655                 goto out_unlock;
656         }
657 
658         /*
659          * length of <= 0 for resv/unresv/zero is invalid.  length for
660          * alloc/free is ignored completely and we have no idea what userspace
661          * might have set it to, so set it to zero to allow range
662          * checks to pass.
663          */
664         switch (cmd) {
665         case XFS_IOC_ZERO_RANGE:
666         case XFS_IOC_RESVSP:
667         case XFS_IOC_RESVSP64:
668         case XFS_IOC_UNRESVSP:
669         case XFS_IOC_UNRESVSP64:
670                 if (bf->l_len <= 0) {
671                         error = XFS_ERROR(EINVAL);
672                         goto out_unlock;
673                 }
674                 break;
675         default:
676                 bf->l_len = 0;
677                 break;
678         }
679 
680         if (bf->l_start < 0 ||
681             bf->l_start > mp->m_super->s_maxbytes ||
682             bf->l_start + bf->l_len < 0 ||
683             bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) {
684                 error = XFS_ERROR(EINVAL);
685                 goto out_unlock;
686         }
687 
688         switch (cmd) {
689         case XFS_IOC_ZERO_RANGE:
690                 error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
691                 if (!error)
692                         setprealloc = true;
693                 break;
694         case XFS_IOC_RESVSP:
695         case XFS_IOC_RESVSP64:
696                 error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len,
697                                                 XFS_BMAPI_PREALLOC);
698                 if (!error)
699                         setprealloc = true;
700                 break;
701         case XFS_IOC_UNRESVSP:
702         case XFS_IOC_UNRESVSP64:
703                 error = xfs_free_file_space(ip, bf->l_start, bf->l_len);
704                 break;
705         case XFS_IOC_ALLOCSP:
706         case XFS_IOC_ALLOCSP64:
707         case XFS_IOC_FREESP:
708         case XFS_IOC_FREESP64:
709                 if (bf->l_start > XFS_ISIZE(ip)) {
710                         error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
711                                         bf->l_start - XFS_ISIZE(ip), 0);
712                         if (error)
713                                 goto out_unlock;
714                 }
715 
716                 iattr.ia_valid = ATTR_SIZE;
717                 iattr.ia_size = bf->l_start;
718 
719                 error = xfs_setattr_size(ip, &iattr);
720                 if (!error)
721                         clrprealloc = true;
722                 break;
723         default:
724                 ASSERT(0);
725                 error = XFS_ERROR(EINVAL);
726         }
727 
728         if (error)
729                 goto out_unlock;
730 
731         tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
732         error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0);
733         if (error) {
734                 xfs_trans_cancel(tp, 0);
735                 goto out_unlock;
736         }
737 
738         xfs_ilock(ip, XFS_ILOCK_EXCL);
739         xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
740 
741         if (!(ioflags & IO_INVIS)) {
742                 ip->i_d.di_mode &= ~S_ISUID;
743                 if (ip->i_d.di_mode & S_IXGRP)
744                         ip->i_d.di_mode &= ~S_ISGID;
745                 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
746         }
747 
748         if (setprealloc)
749                 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
750         else if (clrprealloc)
751                 ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
752 
753         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
754         if (filp->f_flags & O_DSYNC)
755                 xfs_trans_set_sync(tp);
756         error = xfs_trans_commit(tp, 0);
757 
758 out_unlock:
759         xfs_iunlock(ip, XFS_IOLOCK_EXCL);
760         mnt_drop_write_file(filp);
761         return -error;
762 }
763 
764 STATIC int
765 xfs_ioc_bulkstat(
766         xfs_mount_t             *mp,
767         unsigned int            cmd,
768         void                    __user *arg)
769 {
770         xfs_fsop_bulkreq_t      bulkreq;
771         int                     count;  /* # of records returned */
772         xfs_ino_t               inlast; /* last inode number */
773         int                     done;
774         int                     error;
775 
776         /* done = 1 if there are more stats to get and if bulkstat */
777         /* should be called again (unused here, but used in dmapi) */
778 
779         if (!capable(CAP_SYS_ADMIN))
780                 return -EPERM;
781 
782         if (XFS_FORCED_SHUTDOWN(mp))
783                 return -XFS_ERROR(EIO);
784 
785         if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
786                 return -XFS_ERROR(EFAULT);
787 
788         if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
789                 return -XFS_ERROR(EFAULT);
790 
791         if ((count = bulkreq.icount) <= 0)
792                 return -XFS_ERROR(EINVAL);
793 
794         if (bulkreq.ubuffer == NULL)
795                 return -XFS_ERROR(EINVAL);
796 
797         if (cmd == XFS_IOC_FSINUMBERS)
798                 error = xfs_inumbers(mp, &inlast, &count,
799                                         bulkreq.ubuffer, xfs_inumbers_fmt);
800         else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
801                 error = xfs_bulkstat_single(mp, &inlast,
802                                                 bulkreq.ubuffer, &done);
803         else    /* XFS_IOC_FSBULKSTAT */
804                 error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
805                                      sizeof(xfs_bstat_t), bulkreq.ubuffer,
806                                      &done);
807 
808         if (error)
809                 return -error;
810 
811         if (bulkreq.ocount != NULL) {
812                 if (copy_to_user(bulkreq.lastip, &inlast,
813                                                 sizeof(xfs_ino_t)))
814                         return -XFS_ERROR(EFAULT);
815 
816                 if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
817                         return -XFS_ERROR(EFAULT);
818         }
819 
820         return 0;
821 }
822 
823 STATIC int
824 xfs_ioc_fsgeometry_v1(
825         xfs_mount_t             *mp,
826         void                    __user *arg)
827 {
828         xfs_fsop_geom_t         fsgeo;
829         int                     error;
830 
831         error = xfs_fs_geometry(mp, &fsgeo, 3);
832         if (error)
833                 return -error;
834 
835         /*
836          * Caller should have passed an argument of type
837          * xfs_fsop_geom_v1_t.  This is a proper subset of the
838          * xfs_fsop_geom_t that xfs_fs_geometry() fills in.
839          */
840         if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))
841                 return -XFS_ERROR(EFAULT);
842         return 0;
843 }
844 
845 STATIC int
846 xfs_ioc_fsgeometry(
847         xfs_mount_t             *mp,
848         void                    __user *arg)
849 {
850         xfs_fsop_geom_t         fsgeo;
851         int                     error;
852 
853         error = xfs_fs_geometry(mp, &fsgeo, 4);
854         if (error)
855                 return -error;
856 
857         if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
858                 return -XFS_ERROR(EFAULT);
859         return 0;
860 }
861 
862 /*
863  * Linux extended inode flags interface.
864  */
865 
866 STATIC unsigned int
867 xfs_merge_ioc_xflags(
868         unsigned int    flags,
869         unsigned int    start)
870 {
871         unsigned int    xflags = start;
872 
873         if (flags & FS_IMMUTABLE_FL)
874                 xflags |= XFS_XFLAG_IMMUTABLE;
875         else
876                 xflags &= ~XFS_XFLAG_IMMUTABLE;
877         if (flags & FS_APPEND_FL)
878                 xflags |= XFS_XFLAG_APPEND;
879         else
880                 xflags &= ~XFS_XFLAG_APPEND;
881         if (flags & FS_SYNC_FL)
882                 xflags |= XFS_XFLAG_SYNC;
883         else
884                 xflags &= ~XFS_XFLAG_SYNC;
885         if (flags & FS_NOATIME_FL)
886                 xflags |= XFS_XFLAG_NOATIME;
887         else
888                 xflags &= ~XFS_XFLAG_NOATIME;
889         if (flags & FS_NODUMP_FL)
890                 xflags |= XFS_XFLAG_NODUMP;
891         else
892                 xflags &= ~XFS_XFLAG_NODUMP;
893 
894         return xflags;
895 }
896 
897 STATIC unsigned int
898 xfs_di2lxflags(
899         __uint16_t      di_flags)
900 {
901         unsigned int    flags = 0;
902 
903         if (di_flags & XFS_DIFLAG_IMMUTABLE)
904                 flags |= FS_IMMUTABLE_FL;
905         if (di_flags & XFS_DIFLAG_APPEND)
906                 flags |= FS_APPEND_FL;
907         if (di_flags & XFS_DIFLAG_SYNC)
908                 flags |= FS_SYNC_FL;
909         if (di_flags & XFS_DIFLAG_NOATIME)
910                 flags |= FS_NOATIME_FL;
911         if (di_flags & XFS_DIFLAG_NODUMP)
912                 flags |= FS_NODUMP_FL;
913         return flags;
914 }
915 
916 STATIC int
917 xfs_ioc_fsgetxattr(
918         xfs_inode_t             *ip,
919         int                     attr,
920         void                    __user *arg)
921 {
922         struct fsxattr          fa;
923 
924         memset(&fa, 0, sizeof(struct fsxattr));
925 
926         xfs_ilock(ip, XFS_ILOCK_SHARED);
927         fa.fsx_xflags = xfs_ip2xflags(ip);
928         fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
929         fa.fsx_projid = xfs_get_projid(ip);
930 
931         if (attr) {
932                 if (ip->i_afp) {
933                         if (ip->i_afp->if_flags & XFS_IFEXTENTS)
934                                 fa.fsx_nextents = ip->i_afp->if_bytes /
935                                                         sizeof(xfs_bmbt_rec_t);
936                         else
937                                 fa.fsx_nextents = ip->i_d.di_anextents;
938                 } else
939                         fa.fsx_nextents = 0;
940         } else {
941                 if (ip->i_df.if_flags & XFS_IFEXTENTS)
942                         fa.fsx_nextents = ip->i_df.if_bytes /
943                                                 sizeof(xfs_bmbt_rec_t);
944                 else
945                         fa.fsx_nextents = ip->i_d.di_nextents;
946         }
947         xfs_iunlock(ip, XFS_ILOCK_SHARED);
948 
949         if (copy_to_user(arg, &fa, sizeof(fa)))
950                 return -EFAULT;
951         return 0;
952 }
953 
954 STATIC void
955 xfs_set_diflags(
956         struct xfs_inode        *ip,
957         unsigned int            xflags)
958 {
959         unsigned int            di_flags;
960 
961         /* can't set PREALLOC this way, just preserve it */
962         di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
963         if (xflags & XFS_XFLAG_IMMUTABLE)
964                 di_flags |= XFS_DIFLAG_IMMUTABLE;
965         if (xflags & XFS_XFLAG_APPEND)
966                 di_flags |= XFS_DIFLAG_APPEND;
967         if (xflags & XFS_XFLAG_SYNC)
968                 di_flags |= XFS_DIFLAG_SYNC;
969         if (xflags & XFS_XFLAG_NOATIME)
970                 di_flags |= XFS_DIFLAG_NOATIME;
971         if (xflags & XFS_XFLAG_NODUMP)
972                 di_flags |= XFS_DIFLAG_NODUMP;
973         if (xflags & XFS_XFLAG_PROJINHERIT)
974                 di_flags |= XFS_DIFLAG_PROJINHERIT;
975         if (xflags & XFS_XFLAG_NODEFRAG)
976                 di_flags |= XFS_DIFLAG_NODEFRAG;
977         if (xflags & XFS_XFLAG_FILESTREAM)
978                 di_flags |= XFS_DIFLAG_FILESTREAM;
979         if (S_ISDIR(ip->i_d.di_mode)) {
980                 if (xflags & XFS_XFLAG_RTINHERIT)
981                         di_flags |= XFS_DIFLAG_RTINHERIT;
982                 if (xflags & XFS_XFLAG_NOSYMLINKS)
983                         di_flags |= XFS_DIFLAG_NOSYMLINKS;
984                 if (xflags & XFS_XFLAG_EXTSZINHERIT)
985                         di_flags |= XFS_DIFLAG_EXTSZINHERIT;
986         } else if (S_ISREG(ip->i_d.di_mode)) {
987                 if (xflags & XFS_XFLAG_REALTIME)
988                         di_flags |= XFS_DIFLAG_REALTIME;
989                 if (xflags & XFS_XFLAG_EXTSIZE)
990                         di_flags |= XFS_DIFLAG_EXTSIZE;
991         }
992 
993         ip->i_d.di_flags = di_flags;
994 }
995 
996 STATIC void
997 xfs_diflags_to_linux(
998         struct xfs_inode        *ip)
999 {
1000         struct inode            *inode = VFS_I(ip);
1001         unsigned int            xflags = xfs_ip2xflags(ip);
1002 
1003         if (xflags & XFS_XFLAG_IMMUTABLE)
1004                 inode->i_flags |= S_IMMUTABLE;
1005         else
1006                 inode->i_flags &= ~S_IMMUTABLE;
1007         if (xflags & XFS_XFLAG_APPEND)
1008                 inode->i_flags |= S_APPEND;
1009         else
1010                 inode->i_flags &= ~S_APPEND;
1011         if (xflags & XFS_XFLAG_SYNC)
1012                 inode->i_flags |= S_SYNC;
1013         else
1014                 inode->i_flags &= ~S_SYNC;
1015         if (xflags & XFS_XFLAG_NOATIME)
1016                 inode->i_flags |= S_NOATIME;
1017         else
1018                 inode->i_flags &= ~S_NOATIME;
1019 }
1020 
1021 #define FSX_PROJID      1
1022 #define FSX_EXTSIZE     2
1023 #define FSX_XFLAGS      4
1024 #define FSX_NONBLOCK    8
1025 
1026 STATIC int
1027 xfs_ioctl_setattr(
1028         xfs_inode_t             *ip,
1029         struct fsxattr          *fa,
1030         int                     mask)
1031 {
1032         struct xfs_mount        *mp = ip->i_mount;
1033         struct xfs_trans        *tp;
1034         unsigned int            lock_flags = 0;
1035         struct xfs_dquot        *udqp = NULL;
1036         struct xfs_dquot        *pdqp = NULL;
1037         struct xfs_dquot        *olddquot = NULL;
1038         int                     code;
1039 
1040         trace_xfs_ioctl_setattr(ip);
1041 
1042         if (mp->m_flags & XFS_MOUNT_RDONLY)
1043                 return XFS_ERROR(EROFS);
1044         if (XFS_FORCED_SHUTDOWN(mp))
1045                 return XFS_ERROR(EIO);
1046 
1047         /*
1048          * Disallow 32bit project ids when projid32bit feature is not enabled.
1049          */
1050         if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
1051                         !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
1052                 return XFS_ERROR(EINVAL);
1053 
1054         /*
1055          * If disk quotas is on, we make sure that the dquots do exist on disk,
1056          * before we start any other transactions. Trying to do this later
1057          * is messy. We don't care to take a readlock to look at the ids
1058          * in inode here, because we can't hold it across the trans_reserve.
1059          * If the IDs do change before we take the ilock, we're covered
1060          * because the i_*dquot fields will get updated anyway.
1061          */
1062         if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
1063                 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
1064                                          ip->i_d.di_gid, fa->fsx_projid,
1065                                          XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
1066                 if (code)
1067                         return code;
1068         }
1069 
1070         /*
1071          * For the other attributes, we acquire the inode lock and
1072          * first do an error checking pass.
1073          */
1074         tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
1075         code = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
1076         if (code)
1077                 goto error_return;
1078 
1079         lock_flags = XFS_ILOCK_EXCL;
1080         xfs_ilock(ip, lock_flags);
1081 
1082         /*
1083          * CAP_FOWNER overrides the following restrictions:
1084          *
1085          * The user ID of the calling process must be equal
1086          * to the file owner ID, except in cases where the
1087          * CAP_FSETID capability is applicable.
1088          */
1089         if (!inode_owner_or_capable(VFS_I(ip))) {
1090                 code = XFS_ERROR(EPERM);
1091                 goto error_return;
1092         }
1093 
1094         /*
1095          * Do a quota reservation only if projid is actually going to change.
1096          * Only allow changing of projid from init_user_ns since it is a
1097          * non user namespace aware identifier.
1098          */
1099         if (mask & FSX_PROJID) {
1100                 if (current_user_ns() != &init_user_ns) {
1101                         code = XFS_ERROR(EINVAL);
1102                         goto error_return;
1103                 }
1104 
1105                 if (XFS_IS_QUOTA_RUNNING(mp) &&
1106                     XFS_IS_PQUOTA_ON(mp) &&
1107                     xfs_get_projid(ip) != fa->fsx_projid) {
1108                         ASSERT(tp);
1109                         code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
1110                                                 pdqp, capable(CAP_FOWNER) ?
1111                                                 XFS_QMOPT_FORCE_RES : 0);
1112                         if (code)       /* out of quota */
1113                                 goto error_return;
1114                 }
1115         }
1116 
1117         if (mask & FSX_EXTSIZE) {
1118                 /*
1119                  * Can't change extent size if any extents are allocated.
1120                  */
1121                 if (ip->i_d.di_nextents &&
1122                     ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
1123                      fa->fsx_extsize)) {
1124                         code = XFS_ERROR(EINVAL);       /* EFBIG? */
1125                         goto error_return;
1126                 }
1127 
1128                 /*
1129                  * Extent size must be a multiple of the appropriate block
1130                  * size, if set at all. It must also be smaller than the
1131                  * maximum extent size supported by the filesystem.
1132                  *
1133                  * Also, for non-realtime files, limit the extent size hint to
1134                  * half the size of the AGs in the filesystem so alignment
1135                  * doesn't result in extents larger than an AG.
1136                  */
1137                 if (fa->fsx_extsize != 0) {
1138                         xfs_extlen_t    size;
1139                         xfs_fsblock_t   extsize_fsb;
1140 
1141                         extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1142                         if (extsize_fsb > MAXEXTLEN) {
1143                                 code = XFS_ERROR(EINVAL);
1144                                 goto error_return;
1145                         }
1146 
1147                         if (XFS_IS_REALTIME_INODE(ip) ||
1148                             ((mask & FSX_XFLAGS) &&
1149                             (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
1150                                 size = mp->m_sb.sb_rextsize <<
1151                                        mp->m_sb.sb_blocklog;
1152                         } else {
1153                                 size = mp->m_sb.sb_blocksize;
1154                                 if (extsize_fsb > mp->m_sb.sb_agblocks / 2) {
1155                                         code = XFS_ERROR(EINVAL);
1156                                         goto error_return;
1157                                 }
1158                         }
1159 
1160                         if (fa->fsx_extsize % size) {
1161                                 code = XFS_ERROR(EINVAL);
1162                                 goto error_return;
1163                         }
1164                 }
1165         }
1166 
1167 
1168         if (mask & FSX_XFLAGS) {
1169                 /*
1170                  * Can't change realtime flag if any extents are allocated.
1171                  */
1172                 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1173                     (XFS_IS_REALTIME_INODE(ip)) !=
1174                     (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1175                         code = XFS_ERROR(EINVAL);       /* EFBIG? */
1176                         goto error_return;
1177                 }
1178 
1179                 /*
1180                  * If realtime flag is set then must have realtime data.
1181                  */
1182                 if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1183                         if ((mp->m_sb.sb_rblocks == 0) ||
1184                             (mp->m_sb.sb_rextsize == 0) ||
1185                             (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
1186                                 code = XFS_ERROR(EINVAL);
1187                                 goto error_return;
1188                         }
1189                 }
1190 
1191                 /*
1192                  * Can't modify an immutable/append-only file unless
1193                  * we have appropriate permission.
1194                  */
1195                 if ((ip->i_d.di_flags &
1196                                 (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
1197                      (fa->fsx_xflags &
1198                                 (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
1199                     !capable(CAP_LINUX_IMMUTABLE)) {
1200                         code = XFS_ERROR(EPERM);
1201                         goto error_return;
1202                 }
1203         }
1204 
1205         xfs_trans_ijoin(tp, ip, 0);
1206 
1207         /*
1208          * Change file ownership.  Must be the owner or privileged.
1209          */
1210         if (mask & FSX_PROJID) {
1211                 /*
1212                  * CAP_FSETID overrides the following restrictions:
1213                  *
1214                  * The set-user-ID and set-group-ID bits of a file will be
1215                  * cleared upon successful return from chown()
1216                  */
1217                 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1218                     !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
1219                         ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1220 
1221                 /*
1222                  * Change the ownerships and register quota modifications
1223                  * in the transaction.
1224                  */
1225                 if (xfs_get_projid(ip) != fa->fsx_projid) {
1226                         if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1227                                 olddquot = xfs_qm_vop_chown(tp, ip,
1228                                                         &ip->i_pdquot, pdqp);
1229                         }
1230                         xfs_set_projid(ip, fa->fsx_projid);
1231 
1232                         /*
1233                          * We may have to rev the inode as well as
1234                          * the superblock version number since projids didn't
1235                          * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1236                          */
1237                         if (ip->i_d.di_version == 1)
1238                                 xfs_bump_ino_vers2(tp, ip);
1239                 }
1240 
1241         }
1242 
1243         if (mask & FSX_EXTSIZE)
1244                 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1245         if (mask & FSX_XFLAGS) {
1246                 xfs_set_diflags(ip, fa->fsx_xflags);
1247                 xfs_diflags_to_linux(ip);
1248         }
1249 
1250         xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
1251         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1252 
1253         XFS_STATS_INC(xs_ig_attrchg);
1254 
1255         /*
1256          * If this is a synchronous mount, make sure that the
1257          * transaction goes to disk before returning to the user.
1258          * This is slightly sub-optimal in that truncates require
1259          * two sync transactions instead of one for wsync filesystems.
1260          * One for the truncate and one for the timestamps since we
1261          * don't want to change the timestamps unless we're sure the
1262          * truncate worked.  Truncates are less than 1% of the laddis
1263          * mix so this probably isn't worth the trouble to optimize.
1264          */
1265         if (mp->m_flags & XFS_MOUNT_WSYNC)
1266                 xfs_trans_set_sync(tp);
1267         code = xfs_trans_commit(tp, 0);
1268         xfs_iunlock(ip, lock_flags);
1269 
1270         /*
1271          * Release any dquot(s) the inode had kept before chown.
1272          */
1273         xfs_qm_dqrele(olddquot);
1274         xfs_qm_dqrele(udqp);
1275         xfs_qm_dqrele(pdqp);
1276 
1277         return code;
1278 
1279  error_return:
1280         xfs_qm_dqrele(udqp);
1281         xfs_qm_dqrele(pdqp);
1282         xfs_trans_cancel(tp, 0);
1283         if (lock_flags)
1284                 xfs_iunlock(ip, lock_flags);
1285         return code;
1286 }
1287 
1288 STATIC int
1289 xfs_ioc_fssetxattr(
1290         xfs_inode_t             *ip,
1291         struct file             *filp,
1292         void                    __user *arg)
1293 {
1294         struct fsxattr          fa;
1295         unsigned int            mask;
1296         int error;
1297 
1298         if (copy_from_user(&fa, arg, sizeof(fa)))
1299                 return -EFAULT;
1300 
1301         mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
1302         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1303                 mask |= FSX_NONBLOCK;
1304 
1305         error = mnt_want_write_file(filp);
1306         if (error)
1307                 return error;
1308         error = xfs_ioctl_setattr(ip, &fa, mask);
1309         mnt_drop_write_file(filp);
1310         return -error;
1311 }
1312 
1313 STATIC int
1314 xfs_ioc_getxflags(
1315         xfs_inode_t             *ip,
1316         void                    __user *arg)
1317 {
1318         unsigned int            flags;
1319 
1320         flags = xfs_di2lxflags(ip->i_d.di_flags);
1321         if (copy_to_user(arg, &flags, sizeof(flags)))
1322                 return -EFAULT;
1323         return 0;
1324 }
1325 
1326 STATIC int
1327 xfs_ioc_setxflags(
1328         xfs_inode_t             *ip,
1329         struct file             *filp,
1330         void                    __user *arg)
1331 {
1332         struct fsxattr          fa;
1333         unsigned int            flags;
1334         unsigned int            mask;
1335         int error;
1336 
1337         if (copy_from_user(&flags, arg, sizeof(flags)))
1338                 return -EFAULT;
1339 
1340         if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
1341                       FS_NOATIME_FL | FS_NODUMP_FL | \
1342                       FS_SYNC_FL))
1343                 return -EOPNOTSUPP;
1344 
1345         mask = FSX_XFLAGS;
1346         if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1347                 mask |= FSX_NONBLOCK;
1348         fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
1349 
1350         error = mnt_want_write_file(filp);
1351         if (error)
1352                 return error;
1353         error = xfs_ioctl_setattr(ip, &fa, mask);
1354         mnt_drop_write_file(filp);
1355         return -error;
1356 }
1357 
1358 STATIC int
1359 xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1360 {
1361         struct getbmap __user   *base = *ap;
1362 
1363         /* copy only getbmap portion (not getbmapx) */
1364         if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1365                 return XFS_ERROR(EFAULT);
1366 
1367         *ap += sizeof(struct getbmap);
1368         return 0;
1369 }
1370 
1371 STATIC int
1372 xfs_ioc_getbmap(
1373         struct xfs_inode        *ip,
1374         int                     ioflags,
1375         unsigned int            cmd,
1376         void                    __user *arg)
1377 {
1378         struct getbmapx         bmx;
1379         int                     error;
1380 
1381         if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1382                 return -XFS_ERROR(EFAULT);
1383 
1384         if (bmx.bmv_count < 2)
1385                 return -XFS_ERROR(EINVAL);
1386 
1387         bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1388         if (ioflags & IO_INVIS)
1389                 bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1390 
1391         error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1392                             (struct getbmap *)arg+1);
1393         if (error)
1394                 return -error;
1395 
1396         /* copy back header - only size of getbmap */
1397         if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1398                 return -XFS_ERROR(EFAULT);
1399         return 0;
1400 }
1401 
1402 STATIC int
1403 xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1404 {
1405         struct getbmapx __user  *base = *ap;
1406 
1407         if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1408                 return XFS_ERROR(EFAULT);
1409 
1410         *ap += sizeof(struct getbmapx);
1411         return 0;
1412 }
1413 
1414 STATIC int
1415 xfs_ioc_getbmapx(
1416         struct xfs_inode        *ip,
1417         void                    __user *arg)
1418 {
1419         struct getbmapx         bmx;
1420         int                     error;
1421 
1422         if (copy_from_user(&bmx, arg, sizeof(bmx)))
1423                 return -XFS_ERROR(EFAULT);
1424 
1425         if (bmx.bmv_count < 2)
1426                 return -XFS_ERROR(EINVAL);
1427 
1428         if (bmx.bmv_iflags & (~BMV_IF_VALID))
1429                 return -XFS_ERROR(EINVAL);
1430 
1431         error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1432                             (struct getbmapx *)arg+1);
1433         if (error)
1434                 return -error;
1435 
1436         /* copy back header */
1437         if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1438                 return -XFS_ERROR(EFAULT);
1439 
1440         return 0;
1441 }
1442 
1443 int
1444 xfs_ioc_swapext(
1445         xfs_swapext_t   *sxp)
1446 {
1447         xfs_inode_t     *ip, *tip;
1448         struct fd       f, tmp;
1449         int             error = 0;
1450 
1451         /* Pull information for the target fd */
1452         f = fdget((int)sxp->sx_fdtarget);
1453         if (!f.file) {
1454                 error = XFS_ERROR(EINVAL);
1455                 goto out;
1456         }
1457 
1458         if (!(f.file->f_mode & FMODE_WRITE) ||
1459             !(f.file->f_mode & FMODE_READ) ||
1460             (f.file->f_flags & O_APPEND)) {
1461                 error = XFS_ERROR(EBADF);
1462                 goto out_put_file;
1463         }
1464 
1465         tmp = fdget((int)sxp->sx_fdtmp);
1466         if (!tmp.file) {
1467                 error = XFS_ERROR(EINVAL);
1468                 goto out_put_file;
1469         }
1470 
1471         if (!(tmp.file->f_mode & FMODE_WRITE) ||
1472             !(tmp.file->f_mode & FMODE_READ) ||
1473             (tmp.file->f_flags & O_APPEND)) {
1474                 error = XFS_ERROR(EBADF);
1475                 goto out_put_tmp_file;
1476         }
1477 
1478         if (IS_SWAPFILE(file_inode(f.file)) ||
1479             IS_SWAPFILE(file_inode(tmp.file))) {
1480                 error = XFS_ERROR(EINVAL);
1481                 goto out_put_tmp_file;
1482         }
1483 
1484         ip = XFS_I(file_inode(f.file));
1485         tip = XFS_I(file_inode(tmp.file));
1486 
1487         if (ip->i_mount != tip->i_mount) {
1488                 error = XFS_ERROR(EINVAL);
1489                 goto out_put_tmp_file;
1490         }
1491 
1492         if (ip->i_ino == tip->i_ino) {
1493                 error = XFS_ERROR(EINVAL);
1494                 goto out_put_tmp_file;
1495         }
1496 
1497         if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
1498                 error = XFS_ERROR(EIO);
1499                 goto out_put_tmp_file;
1500         }
1501 
1502         error = xfs_swap_extents(ip, tip, sxp);
1503 
1504  out_put_tmp_file:
1505         fdput(tmp);
1506  out_put_file:
1507         fdput(f);
1508  out:
1509         return error;
1510 }
1511 
1512 /*
1513  * Note: some of the ioctl's return positive numbers as a
1514  * byte count indicating success, such as readlink_by_handle.
1515  * So we don't "sign flip" like most other routines.  This means
1516  * true errors need to be returned as a negative value.
1517  */
1518 long
1519 xfs_file_ioctl(
1520         struct file             *filp,
1521         unsigned int            cmd,
1522         unsigned long           p)
1523 {
1524         struct inode            *inode = file_inode(filp);
1525         struct xfs_inode        *ip = XFS_I(inode);
1526         struct xfs_mount        *mp = ip->i_mount;
1527         void                    __user *arg = (void __user *)p;
1528         int                     ioflags = 0;
1529         int                     error;
1530 
1531         if (filp->f_mode & FMODE_NOCMTIME)
1532                 ioflags |= IO_INVIS;
1533 
1534         trace_xfs_file_ioctl(ip);
1535 
1536         switch (cmd) {
1537         case FITRIM:
1538                 return xfs_ioc_trim(mp, arg);
1539         case XFS_IOC_ALLOCSP:
1540         case XFS_IOC_FREESP:
1541         case XFS_IOC_RESVSP:
1542         case XFS_IOC_UNRESVSP:
1543         case XFS_IOC_ALLOCSP64:
1544         case XFS_IOC_FREESP64:
1545         case XFS_IOC_RESVSP64:
1546         case XFS_IOC_UNRESVSP64:
1547         case XFS_IOC_ZERO_RANGE: {
1548                 xfs_flock64_t           bf;
1549 
1550                 if (copy_from_user(&bf, arg, sizeof(bf)))
1551                         return -XFS_ERROR(EFAULT);
1552                 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1553         }
1554         case XFS_IOC_DIOINFO: {
1555                 struct dioattr  da;
1556                 xfs_buftarg_t   *target =
1557                         XFS_IS_REALTIME_INODE(ip) ?
1558                         mp->m_rtdev_targp : mp->m_ddev_targp;
1559 
1560                 da.d_mem =  da.d_miniosz = target->bt_logical_sectorsize;
1561                 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
1562 
1563                 if (copy_to_user(arg, &da, sizeof(da)))
1564                         return -XFS_ERROR(EFAULT);
1565                 return 0;
1566         }
1567 
1568         case XFS_IOC_FSBULKSTAT_SINGLE:
1569         case XFS_IOC_FSBULKSTAT:
1570         case XFS_IOC_FSINUMBERS:
1571                 return xfs_ioc_bulkstat(mp, cmd, arg);
1572 
1573         case XFS_IOC_FSGEOMETRY_V1:
1574                 return xfs_ioc_fsgeometry_v1(mp, arg);
1575 
1576         case XFS_IOC_FSGEOMETRY:
1577                 return xfs_ioc_fsgeometry(mp, arg);
1578 
1579         case XFS_IOC_GETVERSION:
1580                 return put_user(inode->i_generation, (int __user *)arg);
1581 
1582         case XFS_IOC_FSGETXATTR:
1583                 return xfs_ioc_fsgetxattr(ip, 0, arg);
1584         case XFS_IOC_FSGETXATTRA:
1585                 return xfs_ioc_fsgetxattr(ip, 1, arg);
1586         case XFS_IOC_FSSETXATTR:
1587                 return xfs_ioc_fssetxattr(ip, filp, arg);
1588         case XFS_IOC_GETXFLAGS:
1589                 return xfs_ioc_getxflags(ip, arg);
1590         case XFS_IOC_SETXFLAGS:
1591                 return xfs_ioc_setxflags(ip, filp, arg);
1592 
1593         case XFS_IOC_FSSETDM: {
1594                 struct fsdmidata        dmi;
1595 
1596                 if (copy_from_user(&dmi, arg, sizeof(dmi)))
1597                         return -XFS_ERROR(EFAULT);
1598 
1599                 error = mnt_want_write_file(filp);
1600                 if (error)
1601                         return error;
1602 
1603                 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1604                                 dmi.fsd_dmstate);
1605                 mnt_drop_write_file(filp);
1606                 return -error;
1607         }
1608 
1609         case XFS_IOC_GETBMAP:
1610         case XFS_IOC_GETBMAPA:
1611                 return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
1612 
1613         case XFS_IOC_GETBMAPX:
1614                 return xfs_ioc_getbmapx(ip, arg);
1615 
1616         case XFS_IOC_FD_TO_HANDLE:
1617         case XFS_IOC_PATH_TO_HANDLE:
1618         case XFS_IOC_PATH_TO_FSHANDLE: {
1619                 xfs_fsop_handlereq_t    hreq;
1620 
1621                 if (copy_from_user(&hreq, arg, sizeof(hreq)))
1622                         return -XFS_ERROR(EFAULT);
1623                 return xfs_find_handle(cmd, &hreq);
1624         }
1625         case XFS_IOC_OPEN_BY_HANDLE: {
1626                 xfs_fsop_handlereq_t    hreq;
1627 
1628                 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1629                         return -XFS_ERROR(EFAULT);
1630                 return xfs_open_by_handle(filp, &hreq);
1631         }
1632         case XFS_IOC_FSSETDM_BY_HANDLE:
1633                 return xfs_fssetdm_by_handle(filp, arg);
1634 
1635         case XFS_IOC_READLINK_BY_HANDLE: {
1636                 xfs_fsop_handlereq_t    hreq;
1637 
1638                 if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1639                         return -XFS_ERROR(EFAULT);
1640                 return xfs_readlink_by_handle(filp, &hreq);
1641         }
1642         case XFS_IOC_ATTRLIST_BY_HANDLE:
1643                 return xfs_attrlist_by_handle(filp, arg);
1644 
1645         case XFS_IOC_ATTRMULTI_BY_HANDLE:
1646                 return xfs_attrmulti_by_handle(filp, arg);
1647 
1648         case XFS_IOC_SWAPEXT: {
1649                 struct xfs_swapext      sxp;
1650 
1651                 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1652                         return -XFS_ERROR(EFAULT);
1653                 error = mnt_want_write_file(filp);
1654                 if (error)
1655                         return error;
1656                 error = xfs_ioc_swapext(&sxp);
1657                 mnt_drop_write_file(filp);
1658                 return -error;
1659         }
1660 
1661         case XFS_IOC_FSCOUNTS: {
1662                 xfs_fsop_counts_t out;
1663 
1664                 error = xfs_fs_counts(mp, &out);
1665                 if (error)
1666                         return -error;
1667 
1668                 if (copy_to_user(arg, &out, sizeof(out)))
1669                         return -XFS_ERROR(EFAULT);
1670                 return 0;
1671         }
1672 
1673         case XFS_IOC_SET_RESBLKS: {
1674                 xfs_fsop_resblks_t inout;
1675                 __uint64_t         in;
1676 
1677                 if (!capable(CAP_SYS_ADMIN))
1678                         return -EPERM;
1679 
1680                 if (mp->m_flags & XFS_MOUNT_RDONLY)
1681                         return -XFS_ERROR(EROFS);
1682 
1683                 if (copy_from_user(&inout, arg, sizeof(inout)))
1684                         return -XFS_ERROR(EFAULT);
1685 
1686                 error = mnt_want_write_file(filp);
1687                 if (error)
1688                         return error;
1689 
1690                 /* input parameter is passed in resblks field of structure */
1691                 in = inout.resblks;
1692                 error = xfs_reserve_blocks(mp, &in, &inout);
1693                 mnt_drop_write_file(filp);
1694                 if (error)
1695                         return -error;
1696 
1697                 if (copy_to_user(arg, &inout, sizeof(inout)))
1698                         return -XFS_ERROR(EFAULT);
1699                 return 0;
1700         }
1701 
1702         case XFS_IOC_GET_RESBLKS: {
1703                 xfs_fsop_resblks_t out;
1704 
1705                 if (!capable(CAP_SYS_ADMIN))
1706                         return -EPERM;
1707 
1708                 error = xfs_reserve_blocks(mp, NULL, &out);
1709                 if (error)
1710                         return -error;
1711 
1712                 if (copy_to_user(arg, &out, sizeof(out)))
1713                         return -XFS_ERROR(EFAULT);
1714 
1715                 return 0;
1716         }
1717 
1718         case XFS_IOC_FSGROWFSDATA: {
1719                 xfs_growfs_data_t in;
1720 
1721                 if (copy_from_user(&in, arg, sizeof(in)))
1722                         return -XFS_ERROR(EFAULT);
1723 
1724                 error = mnt_want_write_file(filp);
1725                 if (error)
1726                         return error;
1727                 error = xfs_growfs_data(mp, &in);
1728                 mnt_drop_write_file(filp);
1729                 return -error;
1730         }
1731 
1732         case XFS_IOC_FSGROWFSLOG: {
1733                 xfs_growfs_log_t in;
1734 
1735                 if (copy_from_user(&in, arg, sizeof(in)))
1736                         return -XFS_ERROR(EFAULT);
1737 
1738                 error = mnt_want_write_file(filp);
1739                 if (error)
1740                         return error;
1741                 error = xfs_growfs_log(mp, &in);
1742                 mnt_drop_write_file(filp);
1743                 return -error;
1744         }
1745 
1746         case XFS_IOC_FSGROWFSRT: {
1747                 xfs_growfs_rt_t in;
1748 
1749                 if (copy_from_user(&in, arg, sizeof(in)))
1750                         return -XFS_ERROR(EFAULT);
1751 
1752                 error = mnt_want_write_file(filp);
1753                 if (error)
1754                         return error;
1755                 error = xfs_growfs_rt(mp, &in);
1756                 mnt_drop_write_file(filp);
1757                 return -error;
1758         }
1759 
1760         case XFS_IOC_GOINGDOWN: {
1761                 __uint32_t in;
1762 
1763                 if (!capable(CAP_SYS_ADMIN))
1764                         return -EPERM;
1765 
1766                 if (get_user(in, (__uint32_t __user *)arg))
1767                         return -XFS_ERROR(EFAULT);
1768 
1769                 error = xfs_fs_goingdown(mp, in);
1770                 return -error;
1771         }
1772 
1773         case XFS_IOC_ERROR_INJECTION: {
1774                 xfs_error_injection_t in;
1775 
1776                 if (!capable(CAP_SYS_ADMIN))
1777                         return -EPERM;
1778 
1779                 if (copy_from_user(&in, arg, sizeof(in)))
1780                         return -XFS_ERROR(EFAULT);
1781 
1782                 error = xfs_errortag_add(in.errtag, mp);
1783                 return -error;
1784         }
1785 
1786         case XFS_IOC_ERROR_CLEARALL:
1787                 if (!capable(CAP_SYS_ADMIN))
1788                         return -EPERM;
1789 
1790                 error = xfs_errortag_clearall(mp, 1);
1791                 return -error;
1792 
1793         case XFS_IOC_FREE_EOFBLOCKS: {
1794                 struct xfs_fs_eofblocks eofb;
1795                 struct xfs_eofblocks keofb;
1796 
1797                 if (!capable(CAP_SYS_ADMIN))
1798                         return -EPERM;
1799 
1800                 if (mp->m_flags & XFS_MOUNT_RDONLY)
1801                         return -XFS_ERROR(EROFS);
1802 
1803                 if (copy_from_user(&eofb, arg, sizeof(eofb)))
1804                         return -XFS_ERROR(EFAULT);
1805 
1806                 error = xfs_fs_eofblocks_from_user(&eofb, &keofb);
1807                 if (error)
1808                         return -error;
1809 
1810                 return -xfs_icache_free_eofblocks(mp, &keofb);
1811         }
1812 
1813         default:
1814                 return -ENOTTY;
1815         }
1816 }
1817 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp