File Index
Files and directories
Sign in
FILE

ioctl.c

File preview with syntax highlighting.

linux-6.19.14/fs/nilfs2/ioctl.c C
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * NILFS ioctl operations.
   4 *
   5 * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation.
   6 *
   7 * Written by Koji Sato.
   8 */
   9
  10#include <linux/fs.h>
  11#include <linux/wait.h>
  12#include <linux/slab.h>
  13#include <linux/capability.h>	/* capable() */
  14#include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
  15#include <linux/vmalloc.h>
  16#include <linux/compat.h>	/* compat_ptr() */
  17#include <linux/mount.h>	/* mnt_want_write_file(), mnt_drop_write_file() */
  18#include <linux/buffer_head.h>
  19#include <linux/fileattr.h>
  20#include <linux/string.h>
  21#include "nilfs.h"
  22#include "segment.h"
  23#include "bmap.h"
  24#include "cpfile.h"
  25#include "sufile.h"
  26#include "dat.h"
  27
  28/**
  29 * nilfs_ioctl_wrap_copy - wrapping function of get/set metadata info
  30 * @nilfs: nilfs object
  31 * @argv: vector of arguments from userspace
  32 * @dir: set of direction flags
  33 * @dofunc: concrete function of get/set metadata info
  34 *
  35 * Description: nilfs_ioctl_wrap_copy() gets/sets metadata info by means of
  36 * calling dofunc() function on the basis of @argv argument.  If successful,
  37 * the requested metadata information is copied to userspace memory.
  38 *
  39 * Return: 0 on success, or one of the following negative error codes on
  40 * failure:
  41 * * %-EFAULT	- Failure during execution of requested operation.
  42 * * %-EINVAL	- Invalid arguments from userspace.
  43 * * %-ENOMEM	- Insufficient memory available.
  44 */
  45static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
  46				 struct nilfs_argv *argv, int dir,
  47				 ssize_t (*dofunc)(struct the_nilfs *,
  48						   __u64 *, int,
  49						   void *, size_t, size_t))
  50{
  51	void *buf;
  52	void __user *base = u64_to_user_ptr(argv->v_base);
  53	size_t maxmembs, total, n;
  54	ssize_t nr;
  55	int ret, i;
  56	__u64 pos, ppos;
  57
  58	if (argv->v_nmembs == 0)
  59		return 0;
  60
  61	if ((size_t)argv->v_size > PAGE_SIZE)
  62		return -EINVAL;
  63
  64	/*
  65	 * Reject pairs of a start item position (argv->v_index) and a
  66	 * total count (argv->v_nmembs) which leads position 'pos' to
  67	 * overflow by the increment at the end of the loop.
  68	 */
  69	if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
  70		return -EINVAL;
  71
  72	buf = (void *)get_zeroed_page(GFP_NOFS);
  73	if (unlikely(!buf))
  74		return -ENOMEM;
  75	maxmembs = PAGE_SIZE / argv->v_size;
  76
  77	ret = 0;
  78	total = 0;
  79	pos = argv->v_index;
  80	for (i = 0; i < argv->v_nmembs; i += n) {
  81		n = (argv->v_nmembs - i < maxmembs) ?
  82			argv->v_nmembs - i : maxmembs;
  83		if ((dir & _IOC_WRITE) &&
  84		    copy_from_user(buf, base + argv->v_size * i,
  85				   argv->v_size * n)) {
  86			ret = -EFAULT;
  87			break;
  88		}
  89		ppos = pos;
  90		nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
  91			       n);
  92		if (nr < 0) {
  93			ret = nr;
  94			break;
  95		}
  96		if ((dir & _IOC_READ) &&
  97		    copy_to_user(base + argv->v_size * i, buf,
  98				 argv->v_size * nr)) {
  99			ret = -EFAULT;
 100			break;
 101		}
 102		total += nr;
 103		if ((size_t)nr < n)
 104			break;
 105		if (pos == ppos)
 106			pos += n;
 107	}
 108	argv->v_nmembs = total;
 109
 110	free_pages((unsigned long)buf, 0);
 111	return ret;
 112}
 113
 114/**
 115 * nilfs_fileattr_get - retrieve miscellaneous file attributes
 116 * @dentry: the object to retrieve from
 117 * @fa:     fileattr pointer
 118 *
 119 * Return: always 0 as success.
 120 */
 121int nilfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
 122{
 123	struct inode *inode = d_inode(dentry);
 124
 125	fileattr_fill_flags(fa, NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE);
 126
 127	return 0;
 128}
 129
 130/**
 131 * nilfs_fileattr_set - change miscellaneous file attributes
 132 * @idmap:  idmap of the mount
 133 * @dentry: the object to change
 134 * @fa:     fileattr pointer
 135 *
 136 * Return: 0 on success, or a negative error code on failure.
 137 */
 138int nilfs_fileattr_set(struct mnt_idmap *idmap,
 139		       struct dentry *dentry, struct file_kattr *fa)
 140{
 141	struct inode *inode = d_inode(dentry);
 142	struct nilfs_transaction_info ti;
 143	unsigned int flags, oldflags;
 144	int ret;
 145
 146	if (fileattr_has_fsx(fa))
 147		return -EOPNOTSUPP;
 148
 149	flags = nilfs_mask_flags(inode->i_mode, fa->flags);
 150
 151	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
 152	if (ret)
 153		return ret;
 154
 155	oldflags = NILFS_I(inode)->i_flags & ~FS_FL_USER_MODIFIABLE;
 156	NILFS_I(inode)->i_flags = oldflags | (flags & FS_FL_USER_MODIFIABLE);
 157
 158	nilfs_set_inode_flags(inode);
 159	inode_set_ctime_current(inode);
 160	if (IS_SYNC(inode))
 161		nilfs_set_transaction_flag(NILFS_TI_SYNC);
 162
 163	nilfs_mark_inode_dirty(inode);
 164	return nilfs_transaction_commit(inode->i_sb);
 165}
 166
 167/**
 168 * nilfs_ioctl_getversion - get info about a file's version (generation number)
 169 * @inode: inode object
 170 * @argp:  userspace memory where the generation number of @inode is stored
 171 *
 172 * Return: 0 on success, or %-EFAULT on error.
 173 */
 174static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
 175{
 176	return put_user(inode->i_generation, (int __user *)argp);
 177}
 178
 179/**
 180 * nilfs_ioctl_change_cpmode - change checkpoint mode (checkpoint/snapshot)
 181 * @inode: inode object
 182 * @filp: file object
 183 * @cmd: ioctl's request code
 184 * @argp: pointer on argument from userspace
 185 *
 186 * Description: nilfs_ioctl_change_cpmode() function changes mode of
 187 * given checkpoint between checkpoint and snapshot state. This ioctl
 188 * is used in chcp and mkcp utilities.
 189 *
 190 * Return: 0 on success, or one of the following negative error codes on
 191 * failure:
 192 * %-EFAULT	- Failure during checkpoint mode changing.
 193 * %-EPERM	- Operation not permitted.
 194 */
 195static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
 196				     unsigned int cmd, void __user *argp)
 197{
 198	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 199	struct nilfs_transaction_info ti;
 200	struct nilfs_cpmode cpmode;
 201	int ret;
 202
 203	if (!capable(CAP_SYS_ADMIN))
 204		return -EPERM;
 205
 206	ret = mnt_want_write_file(filp);
 207	if (ret)
 208		return ret;
 209
 210	ret = -EFAULT;
 211	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
 212		goto out;
 213
 214	mutex_lock(&nilfs->ns_snapshot_mount_mutex);
 215
 216	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 217	ret = nilfs_cpfile_change_cpmode(
 218		nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
 219	if (unlikely(ret < 0))
 220		nilfs_transaction_abort(inode->i_sb);
 221	else
 222		nilfs_transaction_commit(inode->i_sb); /* never fails */
 223
 224	mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
 225out:
 226	mnt_drop_write_file(filp);
 227	return ret;
 228}
 229
 230/**
 231 * nilfs_ioctl_delete_checkpoint - remove checkpoint
 232 * @inode: inode object
 233 * @filp: file object
 234 * @cmd: ioctl's request code
 235 * @argp: pointer on argument from userspace
 236 *
 237 * Description: nilfs_ioctl_delete_checkpoint() function removes
 238 * checkpoint from NILFS2 file system. This ioctl is used in rmcp
 239 * utility.
 240 *
 241 * Return: 0 on success, or one of the following negative error codes on
 242 * failure:
 243 * %-EFAULT	- Failure during checkpoint removing.
 244 * %-EPERM	- Operation not permitted.
 245 */
 246static int
 247nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
 248			      unsigned int cmd, void __user *argp)
 249{
 250	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 251	struct nilfs_transaction_info ti;
 252	__u64 cno;
 253	int ret;
 254
 255	if (!capable(CAP_SYS_ADMIN))
 256		return -EPERM;
 257
 258	ret = mnt_want_write_file(filp);
 259	if (ret)
 260		return ret;
 261
 262	ret = -EFAULT;
 263	if (copy_from_user(&cno, argp, sizeof(cno)))
 264		goto out;
 265
 266	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 267	ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
 268	if (unlikely(ret < 0))
 269		nilfs_transaction_abort(inode->i_sb);
 270	else
 271		nilfs_transaction_commit(inode->i_sb); /* never fails */
 272out:
 273	mnt_drop_write_file(filp);
 274	return ret;
 275}
 276
 277/**
 278 * nilfs_ioctl_do_get_cpinfo - callback method getting info about checkpoints
 279 * @nilfs: nilfs object
 280 * @posp: pointer on array of checkpoint's numbers
 281 * @flags: checkpoint mode (checkpoint or snapshot)
 282 * @buf: buffer for storing checkponts' info
 283 * @size: size in bytes of one checkpoint info item in array
 284 * @nmembs: number of checkpoints in array (numbers and infos)
 285 *
 286 * Description: nilfs_ioctl_do_get_cpinfo() function returns info about
 287 * requested checkpoints. The NILFS_IOCTL_GET_CPINFO ioctl is used in
 288 * lscp utility and by nilfs_cleanerd daemon.
 289 *
 290 * Return: Count of nilfs_cpinfo structures in output buffer.
 291 */
 292static ssize_t
 293nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 294			  void *buf, size_t size, size_t nmembs)
 295{
 296	int ret;
 297
 298	down_read(&nilfs->ns_segctor_sem);
 299	ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
 300				      size, nmembs);
 301	up_read(&nilfs->ns_segctor_sem);
 302	return ret;
 303}
 304
 305/**
 306 * nilfs_ioctl_get_cpstat - get checkpoints statistics
 307 * @inode: inode object
 308 * @filp: file object
 309 * @cmd: ioctl's request code
 310 * @argp: pointer on argument from userspace
 311 *
 312 * Description: nilfs_ioctl_get_cpstat() returns information about checkpoints.
 313 * The NILFS_IOCTL_GET_CPSTAT ioctl is used by lscp, rmcp utilities
 314 * and by nilfs_cleanerd daemon.  The checkpoint statistics are copied to
 315 * the userspace memory pointed to by @argp.
 316 *
 317 * Return: 0 on success, or one of the following negative error codes on
 318 * failure:
 319 * * %-EFAULT	- Failure during getting checkpoints statistics.
 320 * * %-EIO	- I/O error.
 321 * * %-ENOMEM	- Insufficient memory available.
 322 */
 323static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
 324				  unsigned int cmd, void __user *argp)
 325{
 326	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 327	struct nilfs_cpstat cpstat;
 328	int ret;
 329
 330	down_read(&nilfs->ns_segctor_sem);
 331	ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
 332	up_read(&nilfs->ns_segctor_sem);
 333	if (ret < 0)
 334		return ret;
 335
 336	if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
 337		ret = -EFAULT;
 338	return ret;
 339}
 340
 341/**
 342 * nilfs_ioctl_do_get_suinfo - callback method getting segment usage info
 343 * @nilfs: nilfs object
 344 * @posp: pointer on array of segment numbers
 345 * @flags: *not used*
 346 * @buf: buffer for storing suinfo array
 347 * @size: size in bytes of one suinfo item in array
 348 * @nmembs: count of segment numbers and suinfos in array
 349 *
 350 * Description: nilfs_ioctl_do_get_suinfo() function returns segment usage
 351 * info about requested segments. The NILFS_IOCTL_GET_SUINFO ioctl is used
 352 * in lssu, nilfs_resize utilities and by nilfs_cleanerd daemon.
 353 *
 354 * Return: Count of nilfs_suinfo structures in output buffer on success,
 355 * or a negative error code on failure.
 356 */
 357static ssize_t
 358nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 359			  void *buf, size_t size, size_t nmembs)
 360{
 361	int ret;
 362
 363	down_read(&nilfs->ns_segctor_sem);
 364	ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
 365				      nmembs);
 366	up_read(&nilfs->ns_segctor_sem);
 367	return ret;
 368}
 369
 370/**
 371 * nilfs_ioctl_get_sustat - get segment usage statistics
 372 * @inode: inode object
 373 * @filp: file object
 374 * @cmd: ioctl's request code
 375 * @argp: pointer on argument from userspace
 376 *
 377 * Description: nilfs_ioctl_get_sustat() returns segment usage statistics.
 378 * The NILFS_IOCTL_GET_SUSTAT ioctl is used in lssu, nilfs_resize utilities
 379 * and by nilfs_cleanerd daemon.  The requested segment usage information is
 380 * copied to the userspace memory pointed to by @argp.
 381 *
 382 * Return: 0 on success, or one of the following negative error codes on
 383 * failure:
 384 * * %-EFAULT	- Failure during getting segment usage statistics.
 385 * * %-EIO	- I/O error.
 386 * * %-ENOMEM	- Insufficient memory available.
 387 */
 388static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
 389				  unsigned int cmd, void __user *argp)
 390{
 391	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 392	struct nilfs_sustat sustat;
 393	int ret;
 394
 395	down_read(&nilfs->ns_segctor_sem);
 396	ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
 397	up_read(&nilfs->ns_segctor_sem);
 398	if (ret < 0)
 399		return ret;
 400
 401	if (copy_to_user(argp, &sustat, sizeof(sustat)))
 402		ret = -EFAULT;
 403	return ret;
 404}
 405
 406/**
 407 * nilfs_ioctl_do_get_vinfo - callback method getting virtual blocks info
 408 * @nilfs: nilfs object
 409 * @posp: *not used*
 410 * @flags: *not used*
 411 * @buf: buffer for storing array of nilfs_vinfo structures
 412 * @size: size in bytes of one vinfo item in array
 413 * @nmembs: count of vinfos in array
 414 *
 415 * Description: nilfs_ioctl_do_get_vinfo() function returns information
 416 * on virtual block addresses. The NILFS_IOCTL_GET_VINFO ioctl is used
 417 * by nilfs_cleanerd daemon.
 418 *
 419 * Return: Count of nilfs_vinfo structures in output buffer on success, or
 420 * a negative error code on failure.
 421 */
 422static ssize_t
 423nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 424			 void *buf, size_t size, size_t nmembs)
 425{
 426	int ret;
 427
 428	down_read(&nilfs->ns_segctor_sem);
 429	ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
 430	up_read(&nilfs->ns_segctor_sem);
 431	return ret;
 432}
 433
 434/**
 435 * nilfs_ioctl_do_get_bdescs - callback method getting disk block descriptors
 436 * @nilfs: nilfs object
 437 * @posp: *not used*
 438 * @flags: *not used*
 439 * @buf: buffer for storing array of nilfs_bdesc structures
 440 * @size: size in bytes of one bdesc item in array
 441 * @nmembs: count of bdescs in array
 442 *
 443 * Description: nilfs_ioctl_do_get_bdescs() function returns information
 444 * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl
 445 * is used by nilfs_cleanerd daemon.
 446 *
 447 * Return: Count of nilfs_bdescs structures in output buffer on success, or
 448 * a negative error code on failure.
 449 */
 450static ssize_t
 451nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
 452			  void *buf, size_t size, size_t nmembs)
 453{
 454	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
 455	struct nilfs_bdesc *bdescs = buf;
 456	int ret, i;
 457
 458	down_read(&nilfs->ns_segctor_sem);
 459	for (i = 0; i < nmembs; i++) {
 460		ret = nilfs_bmap_lookup_at_level(bmap,
 461						 bdescs[i].bd_offset,
 462						 bdescs[i].bd_level + 1,
 463						 &bdescs[i].bd_blocknr);
 464		if (ret < 0) {
 465			if (ret != -ENOENT) {
 466				up_read(&nilfs->ns_segctor_sem);
 467				return ret;
 468			}
 469			bdescs[i].bd_blocknr = 0;
 470		}
 471	}
 472	up_read(&nilfs->ns_segctor_sem);
 473	return nmembs;
 474}
 475
 476/**
 477 * nilfs_ioctl_get_bdescs - get disk block descriptors
 478 * @inode: inode object
 479 * @filp: file object
 480 * @cmd: ioctl's request code
 481 * @argp: pointer on argument from userspace
 482 *
 483 * Description: nilfs_ioctl_do_get_bdescs() function returns information
 484 * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl
 485 * is used by nilfs_cleanerd daemon.  If successful, disk block descriptors
 486 * are copied to userspace pointer @argp.
 487 *
 488 * Return: 0 on success, or one of the following negative error codes on
 489 * failure:
 490 * * %-EFAULT	- Failure during getting disk block descriptors.
 491 * * %-EINVAL	- Invalid arguments from userspace.
 492 * * %-EIO	- I/O error.
 493 * * %-ENOMEM	- Insufficient memory available.
 494 */
 495static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
 496				  unsigned int cmd, void __user *argp)
 497{
 498	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 499	struct nilfs_argv argv;
 500	int ret;
 501
 502	if (copy_from_user(&argv, argp, sizeof(argv)))
 503		return -EFAULT;
 504
 505	if (argv.v_size != sizeof(struct nilfs_bdesc))
 506		return -EINVAL;
 507
 508	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
 509				    nilfs_ioctl_do_get_bdescs);
 510	if (ret < 0)
 511		return ret;
 512
 513	if (copy_to_user(argp, &argv, sizeof(argv)))
 514		ret = -EFAULT;
 515	return ret;
 516}
 517
 518/**
 519 * nilfs_ioctl_move_inode_block - prepare data/node block for moving by GC
 520 * @inode: inode object
 521 * @vdesc: descriptor of virtual block number
 522 * @buffers: list of moving buffers
 523 *
 524 * Description: nilfs_ioctl_move_inode_block() function registers data/node
 525 * buffer in the GC pagecache and submit read request.
 526 *
 527 * Return: 0 on success, or one of the following negative error codes on
 528 * failure:
 529 * * %-EEXIST	- Block conflict detected.
 530 * * %-EIO	- I/O error.
 531 * * %-ENOENT	- Requested block doesn't exist.
 532 * * %-ENOMEM	- Insufficient memory available.
 533 */
 534static int nilfs_ioctl_move_inode_block(struct inode *inode,
 535					struct nilfs_vdesc *vdesc,
 536					struct list_head *buffers)
 537{
 538	struct buffer_head *bh;
 539	int ret;
 540
 541	if (vdesc->vd_flags == 0)
 542		ret = nilfs_gccache_submit_read_data(
 543			inode, vdesc->vd_offset, vdesc->vd_blocknr,
 544			vdesc->vd_vblocknr, &bh);
 545	else
 546		ret = nilfs_gccache_submit_read_node(
 547			inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
 548
 549	if (unlikely(ret < 0)) {
 550		if (ret == -ENOENT)
 551			nilfs_crit(inode->i_sb,
 552				   "%s: invalid virtual block address (%s): ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
 553				   __func__, vdesc->vd_flags ? "node" : "data",
 554				   (unsigned long long)vdesc->vd_ino,
 555				   (unsigned long long)vdesc->vd_cno,
 556				   (unsigned long long)vdesc->vd_offset,
 557				   (unsigned long long)vdesc->vd_blocknr,
 558				   (unsigned long long)vdesc->vd_vblocknr);
 559		return ret;
 560	}
 561	if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
 562		nilfs_crit(inode->i_sb,
 563			   "%s: conflicting %s buffer: ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
 564			   __func__, vdesc->vd_flags ? "node" : "data",
 565			   (unsigned long long)vdesc->vd_ino,
 566			   (unsigned long long)vdesc->vd_cno,
 567			   (unsigned long long)vdesc->vd_offset,
 568			   (unsigned long long)vdesc->vd_blocknr,
 569			   (unsigned long long)vdesc->vd_vblocknr);
 570		brelse(bh);
 571		return -EEXIST;
 572	}
 573	list_add_tail(&bh->b_assoc_buffers, buffers);
 574	return 0;
 575}
 576
 577/**
 578 * nilfs_ioctl_move_blocks - move valid inode's blocks during garbage collection
 579 * @sb: superblock object
 580 * @argv: vector of arguments from userspace
 581 * @buf: array of nilfs_vdesc structures
 582 *
 583 * Description: nilfs_ioctl_move_blocks() function reads valid data/node
 584 * blocks that garbage collector specified with the array of nilfs_vdesc
 585 * structures and stores them into page caches of GC inodes.
 586 *
 587 * Return: Number of processed nilfs_vdesc structures on success, or
 588 * a negative error code on failure.
 589 */
 590static int nilfs_ioctl_move_blocks(struct super_block *sb,
 591				   struct nilfs_argv *argv, void *buf)
 592{
 593	size_t nmembs = argv->v_nmembs;
 594	struct the_nilfs *nilfs = sb->s_fs_info;
 595	struct inode *inode;
 596	struct nilfs_vdesc *vdesc;
 597	struct buffer_head *bh, *n;
 598	LIST_HEAD(buffers);
 599	ino_t ino;
 600	__u64 cno;
 601	int i, ret;
 602
 603	for (i = 0, vdesc = buf; i < nmembs; ) {
 604		ino = vdesc->vd_ino;
 605		cno = vdesc->vd_cno;
 606		inode = nilfs_iget_for_gc(sb, ino, cno);
 607		if (IS_ERR(inode)) {
 608			ret = PTR_ERR(inode);
 609			goto failed;
 610		}
 611		if (list_empty(&NILFS_I(inode)->i_dirty)) {
 612			/*
 613			 * Add the inode to GC inode list. Garbage Collection
 614			 * is serialized and no two processes manipulate the
 615			 * list simultaneously.
 616			 */
 617			igrab(inode);
 618			list_add(&NILFS_I(inode)->i_dirty,
 619				 &nilfs->ns_gc_inodes);
 620		}
 621
 622		do {
 623			ret = nilfs_ioctl_move_inode_block(inode, vdesc,
 624							   &buffers);
 625			if (unlikely(ret < 0)) {
 626				iput(inode);
 627				goto failed;
 628			}
 629			vdesc++;
 630		} while (++i < nmembs &&
 631			 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
 632
 633		iput(inode); /* The inode still remains in GC inode list */
 634	}
 635
 636	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
 637		ret = nilfs_gccache_wait_and_mark_dirty(bh);
 638		if (unlikely(ret < 0)) {
 639			WARN_ON(ret == -EEXIST);
 640			goto failed;
 641		}
 642		list_del_init(&bh->b_assoc_buffers);
 643		brelse(bh);
 644	}
 645	return nmembs;
 646
 647 failed:
 648	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
 649		list_del_init(&bh->b_assoc_buffers);
 650		brelse(bh);
 651	}
 652	return ret;
 653}
 654
 655/**
 656 * nilfs_ioctl_delete_checkpoints - delete checkpoints
 657 * @nilfs: nilfs object
 658 * @argv: vector of arguments from userspace
 659 * @buf: array of periods of checkpoints numbers
 660 *
 661 * Description: nilfs_ioctl_delete_checkpoints() function deletes checkpoints
 662 * in the period from p_start to p_end, excluding p_end itself. The checkpoints
 663 * which have been already deleted are ignored.
 664 *
 665 * Return: Number of processed nilfs_period structures on success, or one of
 666 * the following negative error codes on failure:
 667 * * %-EINVAL	- invalid checkpoints.
 668 * * %-EIO	- I/O error.
 669 * * %-ENOMEM	- Insufficient memory available.
 670 */
 671static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
 672					  struct nilfs_argv *argv, void *buf)
 673{
 674	size_t nmembs = argv->v_nmembs;
 675	struct inode *cpfile = nilfs->ns_cpfile;
 676	struct nilfs_period *periods = buf;
 677	int ret, i;
 678
 679	for (i = 0; i < nmembs; i++) {
 680		ret = nilfs_cpfile_delete_checkpoints(
 681			cpfile, periods[i].p_start, periods[i].p_end);
 682		if (ret < 0)
 683			return ret;
 684	}
 685	return nmembs;
 686}
 687
 688/**
 689 * nilfs_ioctl_free_vblocknrs - free virtual block numbers
 690 * @nilfs: nilfs object
 691 * @argv: vector of arguments from userspace
 692 * @buf: array of virtual block numbers
 693 *
 694 * Description: nilfs_ioctl_free_vblocknrs() function frees
 695 * the virtual block numbers specified by @buf and @argv->v_nmembs.
 696 *
 697 * Return: Number of processed virtual block numbers on success, or one of the
 698 * following negative error codes on failure:
 699 * * %-EIO	- I/O error.
 700 * * %-ENOENT	- Unallocated virtual block number.
 701 * * %-ENOMEM	- Insufficient memory available.
 702 */
 703static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
 704				      struct nilfs_argv *argv, void *buf)
 705{
 706	size_t nmembs = argv->v_nmembs;
 707	int ret;
 708
 709	ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
 710
 711	return (ret < 0) ? ret : nmembs;
 712}
 713
 714/**
 715 * nilfs_ioctl_mark_blocks_dirty - mark blocks dirty
 716 * @nilfs: nilfs object
 717 * @argv: vector of arguments from userspace
 718 * @buf: array of block descriptors
 719 *
 720 * Description: nilfs_ioctl_mark_blocks_dirty() function marks
 721 * metadata file or data blocks as dirty.
 722 *
 723 * Return: Number of processed block descriptors on success, or one of the
 724 * following negative error codes on failure:
 725 * * %-EIO	- I/O error.
 726 * * %-ENOENT	- Non-existent block (hole block).
 727 * * %-ENOMEM	- Insufficient memory available.
 728 */
 729static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
 730					 struct nilfs_argv *argv, void *buf)
 731{
 732	size_t nmembs = argv->v_nmembs;
 733	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
 734	struct nilfs_bdesc *bdescs = buf;
 735	struct buffer_head *bh;
 736	int ret, i;
 737
 738	for (i = 0; i < nmembs; i++) {
 739		/* XXX: use macro or inline func to check liveness */
 740		ret = nilfs_bmap_lookup_at_level(bmap,
 741						 bdescs[i].bd_offset,
 742						 bdescs[i].bd_level + 1,
 743						 &bdescs[i].bd_blocknr);
 744		if (ret < 0) {
 745			if (ret != -ENOENT)
 746				return ret;
 747			bdescs[i].bd_blocknr = 0;
 748		}
 749		if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
 750			/* skip dead block */
 751			continue;
 752		if (bdescs[i].bd_level == 0) {
 753			ret = nilfs_mdt_get_block(nilfs->ns_dat,
 754						  bdescs[i].bd_offset,
 755						  false, NULL, &bh);
 756			if (unlikely(ret)) {
 757				WARN_ON(ret == -ENOENT);
 758				return ret;
 759			}
 760			mark_buffer_dirty(bh);
 761			nilfs_mdt_mark_dirty(nilfs->ns_dat);
 762			put_bh(bh);
 763		} else {
 764			ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
 765					      bdescs[i].bd_level);
 766			if (ret < 0) {
 767				WARN_ON(ret == -ENOENT);
 768				return ret;
 769			}
 770		}
 771	}
 772	return nmembs;
 773}
 774
 775int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
 776				       struct nilfs_argv *argv, void **kbufs)
 777{
 778	const char *msg;
 779	int ret;
 780
 781	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
 782	if (ret < 0) {
 783		/*
 784		 * can safely abort because checkpoints can be removed
 785		 * independently.
 786		 */
 787		msg = "cannot delete checkpoints";
 788		goto failed;
 789	}
 790	ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
 791	if (ret < 0) {
 792		/*
 793		 * can safely abort because DAT file is updated atomically
 794		 * using a copy-on-write technique.
 795		 */
 796		msg = "cannot delete virtual blocks from DAT file";
 797		goto failed;
 798	}
 799	ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
 800	if (ret < 0) {
 801		/*
 802		 * can safely abort because the operation is nondestructive.
 803		 */
 804		msg = "cannot mark copying blocks dirty";
 805		goto failed;
 806	}
 807	return 0;
 808
 809 failed:
 810	nilfs_err(nilfs->ns_sb, "error %d preparing GC: %s", ret, msg);
 811	return ret;
 812}
 813
 814/**
 815 * nilfs_ioctl_clean_segments - clean segments
 816 * @inode: inode object
 817 * @filp: file object
 818 * @cmd: ioctl's request code
 819 * @argp: pointer on argument from userspace
 820 *
 821 * Description: nilfs_ioctl_clean_segments() function makes garbage
 822 * collection operation in the environment of requested parameters
 823 * from userspace. The NILFS_IOCTL_CLEAN_SEGMENTS ioctl is used by
 824 * nilfs_cleanerd daemon.
 825 *
 826 * Return: 0 on success, or a negative error code on failure.
 827 */
 828static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
 829				      unsigned int cmd, void __user *argp)
 830{
 831	struct nilfs_argv argv[5];
 832	static const size_t argsz[5] = {
 833		sizeof(struct nilfs_vdesc),
 834		sizeof(struct nilfs_period),
 835		sizeof(__u64),
 836		sizeof(struct nilfs_bdesc),
 837		sizeof(__u64),
 838	};
 839	void *kbufs[5];
 840	struct the_nilfs *nilfs;
 841	size_t len, nsegs;
 842	int n, ret;
 843
 844	if (!capable(CAP_SYS_ADMIN))
 845		return -EPERM;
 846
 847	ret = mnt_want_write_file(filp);
 848	if (ret)
 849		return ret;
 850
 851	ret = -EFAULT;
 852	if (copy_from_user(argv, argp, sizeof(argv)))
 853		goto out;
 854
 855	ret = -EINVAL;
 856	nsegs = argv[4].v_nmembs;
 857	if (argv[4].v_size != argsz[4])
 858		goto out;
 859
 860	/*
 861	 * argv[4] points to segment numbers this ioctl cleans.  We
 862	 * use kmalloc() for its buffer because the memory used for the
 863	 * segment numbers is small enough.
 864	 */
 865	kbufs[4] = memdup_array_user(u64_to_user_ptr(argv[4].v_base),
 866				     nsegs, sizeof(__u64));
 867	if (IS_ERR(kbufs[4])) {
 868		ret = PTR_ERR(kbufs[4]);
 869		goto out;
 870	}
 871	nilfs = inode->i_sb->s_fs_info;
 872
 873	for (n = 0; n < 4; n++) {
 874		ret = -EINVAL;
 875		if (argv[n].v_size != argsz[n])
 876			goto out_free;
 877
 878		if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
 879			goto out_free;
 880
 881		if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
 882			goto out_free;
 883
 884		len = argv[n].v_size * argv[n].v_nmembs;
 885		if (len == 0) {
 886			kbufs[n] = NULL;
 887			continue;
 888		}
 889
 890		kbufs[n] = vmemdup_user(u64_to_user_ptr(argv[n].v_base), len);
 891		if (IS_ERR(kbufs[n])) {
 892			ret = PTR_ERR(kbufs[n]);
 893			goto out_free;
 894		}
 895	}
 896
 897	/*
 898	 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
 899	 * which will operates an inode list without blocking.
 900	 * To protect the list from concurrent operations,
 901	 * nilfs_ioctl_move_blocks should be atomic operation.
 902	 */
 903	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
 904		ret = -EBUSY;
 905		goto out_free;
 906	}
 907
 908	ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
 909	if (ret < 0) {
 910		nilfs_err(inode->i_sb,
 911			  "error %d preparing GC: cannot read source blocks",
 912			  ret);
 913	} else {
 914		if (nilfs_sb_need_update(nilfs))
 915			set_nilfs_discontinued(nilfs);
 916		ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
 917	}
 918
 919	nilfs_remove_all_gcinodes(nilfs);
 920	clear_nilfs_gc_running(nilfs);
 921
 922out_free:
 923	while (--n >= 0)
 924		kvfree(kbufs[n]);
 925	kfree(kbufs[4]);
 926out:
 927	mnt_drop_write_file(filp);
 928	return ret;
 929}
 930
 931/**
 932 * nilfs_ioctl_sync - make a checkpoint
 933 * @inode: inode object
 934 * @filp: file object
 935 * @cmd: ioctl's request code
 936 * @argp: pointer on argument from userspace
 937 *
 938 * Description: nilfs_ioctl_sync() function constructs a logical segment
 939 * for checkpointing.  This function guarantees that all modified data
 940 * and metadata are written out to the device when it successfully
 941 * returned.
 942 *
 943 * Return: 0 on success, or one of the following negative error codes on
 944 * failure:
 945 * * %-EFAULT		- Failure during execution of requested operation.
 946 * * %-EIO		- I/O error.
 947 * * %-ENOMEM		- Insufficient memory available.
 948 * * %-ENOSPC		- No space left on device (only in a panic state).
 949 * * %-ERESTARTSYS	- Interrupted.
 950 * * %-EROFS		- Read only filesystem.
 951 */
 952static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
 953			    unsigned int cmd, void __user *argp)
 954{
 955	__u64 cno;
 956	int ret;
 957	struct the_nilfs *nilfs;
 958
 959	ret = nilfs_construct_segment(inode->i_sb);
 960	if (ret < 0)
 961		return ret;
 962
 963	nilfs = inode->i_sb->s_fs_info;
 964	ret = nilfs_flush_device(nilfs);
 965	if (ret < 0)
 966		return ret;
 967
 968	if (argp != NULL) {
 969		down_read(&nilfs->ns_segctor_sem);
 970		cno = nilfs->ns_cno - 1;
 971		up_read(&nilfs->ns_segctor_sem);
 972		if (copy_to_user(argp, &cno, sizeof(cno)))
 973			return -EFAULT;
 974	}
 975	return 0;
 976}
 977
 978/**
 979 * nilfs_ioctl_resize - resize NILFS2 volume
 980 * @inode: inode object
 981 * @filp: file object
 982 * @argp: pointer on argument from userspace
 983 *
 984 * Return: 0 on success, or a negative error code on failure.
 985 */
 986static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
 987			      void __user *argp)
 988{
 989	__u64 newsize;
 990	int ret = -EPERM;
 991
 992	if (!capable(CAP_SYS_ADMIN))
 993		goto out;
 994
 995	ret = mnt_want_write_file(filp);
 996	if (ret)
 997		goto out;
 998
 999	ret = -EFAULT;
1000	if (copy_from_user(&newsize, argp, sizeof(newsize)))
1001		goto out_drop_write;
1002
1003	ret = nilfs_resize_fs(inode->i_sb, newsize);
1004
1005out_drop_write:
1006	mnt_drop_write_file(filp);
1007out:
1008	return ret;
1009}
1010
1011/**
1012 * nilfs_ioctl_trim_fs() - trim ioctl handle function
1013 * @inode: inode object
1014 * @argp: pointer on argument from userspace
1015 *
1016 * Description: nilfs_ioctl_trim_fs is the FITRIM ioctl handle function. It
1017 * checks the arguments from userspace and calls nilfs_sufile_trim_fs, which
1018 * performs the actual trim operation.
1019 *
1020 * Return: 0 on success, or a negative error code on failure.
1021 */
1022static int nilfs_ioctl_trim_fs(struct inode *inode, void __user *argp)
1023{
1024	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1025	struct fstrim_range range;
1026	int ret;
1027
1028	if (!capable(CAP_SYS_ADMIN))
1029		return -EPERM;
1030
1031	if (!bdev_max_discard_sectors(nilfs->ns_bdev))
1032		return -EOPNOTSUPP;
1033
1034	if (copy_from_user(&range, argp, sizeof(range)))
1035		return -EFAULT;
1036
1037	range.minlen = max_t(u64, range.minlen,
1038			     bdev_discard_granularity(nilfs->ns_bdev));
1039
1040	down_read(&nilfs->ns_segctor_sem);
1041	ret = nilfs_sufile_trim_fs(nilfs->ns_sufile, &range);
1042	up_read(&nilfs->ns_segctor_sem);
1043
1044	if (ret < 0)
1045		return ret;
1046
1047	if (copy_to_user(argp, &range, sizeof(range)))
1048		return -EFAULT;
1049
1050	return 0;
1051}
1052
1053/**
1054 * nilfs_ioctl_set_alloc_range - limit range of segments to be allocated
1055 * @inode: inode object
1056 * @argp: pointer on argument from userspace
1057 *
1058 * Description: nilfs_ioctl_set_alloc_range() function defines lower limit
1059 * of segments in bytes and upper limit of segments in bytes.
1060 * The NILFS_IOCTL_SET_ALLOC_RANGE is used by nilfs_resize utility.
1061 *
1062 * Return: 0 on success, or a negative error code on failure.
1063 */
1064static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
1065{
1066	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1067	__u64 range[2];
1068	__u64 minseg, maxseg;
1069	unsigned long segbytes;
1070	int ret = -EPERM;
1071
1072	if (!capable(CAP_SYS_ADMIN))
1073		goto out;
1074
1075	ret = -EFAULT;
1076	if (copy_from_user(range, argp, sizeof(__u64[2])))
1077		goto out;
1078
1079	ret = -ERANGE;
1080	if (range[1] > bdev_nr_bytes(inode->i_sb->s_bdev))
1081		goto out;
1082
1083	segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
1084
1085	minseg = range[0] + segbytes - 1;
1086	minseg = div64_ul(minseg, segbytes);
1087
1088	if (range[1] < 4096)
1089		goto out;
1090
1091	maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
1092	if (maxseg < segbytes)
1093		goto out;
1094
1095	maxseg = div64_ul(maxseg, segbytes);
1096	maxseg--;
1097
1098	ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
1099out:
1100	return ret;
1101}
1102
1103/**
1104 * nilfs_ioctl_get_info - wrapping function of get metadata info
1105 * @inode: inode object
1106 * @filp: file object
1107 * @cmd: ioctl's request code
1108 * @argp: pointer on argument from userspace
1109 * @membsz: size of an item in bytes
1110 * @dofunc: concrete function of getting metadata info
1111 *
1112 * Description: nilfs_ioctl_get_info() gets metadata info by means of
1113 * calling dofunc() function.  The requested metadata information is copied
1114 * to userspace memory @argp.
1115 *
1116 * Return: 0 on success, or one of the following negative error codes on
1117 * failure:
1118 * * %-EFAULT	- Failure during execution of requested operation.
1119 * * %-EINVAL	- Invalid arguments from userspace.
1120 * * %-EIO	- I/O error.
1121 * * %-ENOMEM	- Insufficient memory available.
1122 */
1123static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
1124				unsigned int cmd, void __user *argp,
1125				size_t membsz,
1126				ssize_t (*dofunc)(struct the_nilfs *,
1127						  __u64 *, int,
1128						  void *, size_t, size_t))
1129
1130{
1131	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1132	struct nilfs_argv argv;
1133	int ret;
1134
1135	if (copy_from_user(&argv, argp, sizeof(argv)))
1136		return -EFAULT;
1137
1138	if (argv.v_size < membsz)
1139		return -EINVAL;
1140
1141	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
1142	if (ret < 0)
1143		return ret;
1144
1145	if (copy_to_user(argp, &argv, sizeof(argv)))
1146		ret = -EFAULT;
1147	return ret;
1148}
1149
1150/**
1151 * nilfs_ioctl_set_suinfo - set segment usage info
1152 * @inode: inode object
1153 * @filp: file object
1154 * @cmd: ioctl's request code
1155 * @argp: pointer on argument from userspace
1156 *
1157 * Description: Expects an array of nilfs_suinfo_update structures
1158 * encapsulated in nilfs_argv and updates the segment usage info
1159 * according to the flags in nilfs_suinfo_update.
1160 *
1161 * Return: 0 on success, or one of the following negative error codes on
1162 * failure:
1163 * * %-EEXIST	- Block conflict detected.
1164 * * %-EFAULT	- Error copying input data.
1165 * * %-EINVAL	- Invalid values in input (segment number, flags or nblocks).
1166 * * %-EIO	- I/O error.
1167 * * %-ENOMEM	- Insufficient memory available.
1168 * * %-EPERM	- Not enough permissions.
1169 */
1170static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
1171				unsigned int cmd, void __user *argp)
1172{
1173	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1174	struct nilfs_transaction_info ti;
1175	struct nilfs_argv argv;
1176	size_t len;
1177	void *kbuf;
1178	int ret;
1179
1180	if (!capable(CAP_SYS_ADMIN))
1181		return -EPERM;
1182
1183	ret = mnt_want_write_file(filp);
1184	if (ret)
1185		return ret;
1186
1187	ret = -EFAULT;
1188	if (copy_from_user(&argv, argp, sizeof(argv)))
1189		goto out;
1190
1191	ret = -EINVAL;
1192	if (argv.v_size < sizeof(struct nilfs_suinfo_update))
1193		goto out;
1194
1195	if (argv.v_nmembs > nilfs->ns_nsegments)
1196		goto out;
1197
1198	if (argv.v_nmembs >= UINT_MAX / argv.v_size)
1199		goto out;
1200
1201	len = argv.v_size * argv.v_nmembs;
1202	if (!len) {
1203		ret = 0;
1204		goto out;
1205	}
1206
1207	kbuf = vmemdup_user(u64_to_user_ptr(argv.v_base), len);
1208	if (IS_ERR(kbuf)) {
1209		ret = PTR_ERR(kbuf);
1210		goto out;
1211	}
1212
1213	nilfs_transaction_begin(inode->i_sb, &ti, 0);
1214	ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
1215			argv.v_nmembs);
1216	if (unlikely(ret < 0))
1217		nilfs_transaction_abort(inode->i_sb);
1218	else
1219		nilfs_transaction_commit(inode->i_sb); /* never fails */
1220
1221	kvfree(kbuf);
1222out:
1223	mnt_drop_write_file(filp);
1224	return ret;
1225}
1226
1227/**
1228 * nilfs_ioctl_get_fslabel - get the volume name of the file system
1229 * @sb:   super block instance
1230 * @argp: pointer to userspace memory where the volume name should be stored
1231 *
1232 * Return: 0 on success, %-EFAULT if copying to userspace memory fails.
1233 */
1234static int nilfs_ioctl_get_fslabel(struct super_block *sb, void __user *argp)
1235{
1236	struct the_nilfs *nilfs = sb->s_fs_info;
1237	char label[NILFS_MAX_VOLUME_NAME + 1];
1238
1239	BUILD_BUG_ON(NILFS_MAX_VOLUME_NAME >= FSLABEL_MAX);
1240
1241	down_read(&nilfs->ns_sem);
1242	memtostr_pad(label, nilfs->ns_sbp[0]->s_volume_name);
1243	up_read(&nilfs->ns_sem);
1244
1245	if (copy_to_user(argp, label, sizeof(label)))
1246		return -EFAULT;
1247	return 0;
1248}
1249
1250/**
1251 * nilfs_ioctl_set_fslabel - set the volume name of the file system
1252 * @sb:   super block instance
1253 * @filp: file object
1254 * @argp: pointer to userspace memory that contains the volume name
1255 *
1256 * Return: 0 on success, or one of the following negative error codes on
1257 * failure:
1258 * * %-EFAULT	- Error copying input data.
1259 * * %-EINVAL	- Label length exceeds record size in superblock.
1260 * * %-EIO	- I/O error.
1261 * * %-EPERM	- Operation not permitted (insufficient permissions).
1262 * * %-EROFS	- Read only file system.
1263 */
1264static int nilfs_ioctl_set_fslabel(struct super_block *sb, struct file *filp,
1265				   void __user *argp)
1266{
1267	char label[NILFS_MAX_VOLUME_NAME + 1];
1268	struct the_nilfs *nilfs = sb->s_fs_info;
1269	struct nilfs_super_block **sbp;
1270	size_t len;
1271	int ret;
1272
1273	if (!capable(CAP_SYS_ADMIN))
1274		return -EPERM;
1275
1276	ret = mnt_want_write_file(filp);
1277	if (ret)
1278		return ret;
1279
1280	if (copy_from_user(label, argp, NILFS_MAX_VOLUME_NAME + 1)) {
1281		ret = -EFAULT;
1282		goto out_drop_write;
1283	}
1284
1285	len = strnlen(label, NILFS_MAX_VOLUME_NAME + 1);
1286	if (len > NILFS_MAX_VOLUME_NAME) {
1287		nilfs_err(sb, "unable to set label with more than %zu bytes",
1288			  NILFS_MAX_VOLUME_NAME);
1289		ret = -EINVAL;
1290		goto out_drop_write;
1291	}
1292
1293	down_write(&nilfs->ns_sem);
1294	sbp = nilfs_prepare_super(sb, false);
1295	if (unlikely(!sbp)) {
1296		ret = -EIO;
1297		goto out_unlock;
1298	}
1299
1300	strtomem_pad(sbp[0]->s_volume_name, label, 0);
1301	if (sbp[1])
1302		strtomem_pad(sbp[1]->s_volume_name, label, 0);
1303
1304	ret = nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
1305
1306out_unlock:
1307	up_write(&nilfs->ns_sem);
1308out_drop_write:
1309	mnt_drop_write_file(filp);
1310	return ret;
1311}
1312
1313long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1314{
1315	struct inode *inode = file_inode(filp);
1316	void __user *argp = (void __user *)arg;
1317
1318	switch (cmd) {
1319	case FS_IOC_GETVERSION:
1320		return nilfs_ioctl_getversion(inode, argp);
1321	case NILFS_IOCTL_CHANGE_CPMODE:
1322		return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
1323	case NILFS_IOCTL_DELETE_CHECKPOINT:
1324		return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
1325	case NILFS_IOCTL_GET_CPINFO:
1326		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1327					    sizeof(struct nilfs_cpinfo),
1328					    nilfs_ioctl_do_get_cpinfo);
1329	case NILFS_IOCTL_GET_CPSTAT:
1330		return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
1331	case NILFS_IOCTL_GET_SUINFO:
1332		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1333					    sizeof(struct nilfs_suinfo),
1334					    nilfs_ioctl_do_get_suinfo);
1335	case NILFS_IOCTL_SET_SUINFO:
1336		return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
1337	case NILFS_IOCTL_GET_SUSTAT:
1338		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
1339	case NILFS_IOCTL_GET_VINFO:
1340		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1341					    sizeof(struct nilfs_vinfo),
1342					    nilfs_ioctl_do_get_vinfo);
1343	case NILFS_IOCTL_GET_BDESCS:
1344		return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
1345	case NILFS_IOCTL_CLEAN_SEGMENTS:
1346		return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
1347	case NILFS_IOCTL_SYNC:
1348		return nilfs_ioctl_sync(inode, filp, cmd, argp);
1349	case NILFS_IOCTL_RESIZE:
1350		return nilfs_ioctl_resize(inode, filp, argp);
1351	case NILFS_IOCTL_SET_ALLOC_RANGE:
1352		return nilfs_ioctl_set_alloc_range(inode, argp);
1353	case FITRIM:
1354		return nilfs_ioctl_trim_fs(inode, argp);
1355	case FS_IOC_GETFSLABEL:
1356		return nilfs_ioctl_get_fslabel(inode->i_sb, argp);
1357	case FS_IOC_SETFSLABEL:
1358		return nilfs_ioctl_set_fslabel(inode->i_sb, filp, argp);
1359	default:
1360		return -ENOTTY;
1361	}
1362}
1363
1364#ifdef CONFIG_COMPAT
1365long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1366{
1367	switch (cmd) {
1368	case FS_IOC32_GETVERSION:
1369		cmd = FS_IOC_GETVERSION;
1370		break;
1371	case NILFS_IOCTL_CHANGE_CPMODE:
1372	case NILFS_IOCTL_DELETE_CHECKPOINT:
1373	case NILFS_IOCTL_GET_CPINFO:
1374	case NILFS_IOCTL_GET_CPSTAT:
1375	case NILFS_IOCTL_GET_SUINFO:
1376	case NILFS_IOCTL_SET_SUINFO:
1377	case NILFS_IOCTL_GET_SUSTAT:
1378	case NILFS_IOCTL_GET_VINFO:
1379	case NILFS_IOCTL_GET_BDESCS:
1380	case NILFS_IOCTL_CLEAN_SEGMENTS:
1381	case NILFS_IOCTL_SYNC:
1382	case NILFS_IOCTL_RESIZE:
1383	case NILFS_IOCTL_SET_ALLOC_RANGE:
1384	case FITRIM:
1385	case FS_IOC_GETFSLABEL:
1386	case FS_IOC_SETFSLABEL:
1387		break;
1388	default:
1389		return -ENOIOCTLCMD;
1390	}
1391	return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
1392}
1393#endif
~/ Read-only file preview.