]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - fs/aufs/ioctl.c
Revert "UBUNTU: SAUCE: aufs -- Convert to use xattr handlers"
[mirror_ubuntu-zesty-kernel.git] / fs / aufs / ioctl.c
CommitLineData
5b88fdd9
SF
1/*
2 * Copyright (C) 2005-2016 Junjiro R. Okajima
3 *
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * ioctl
20 * plink-management and readdir in userspace.
21 * assist the pathconf(3) wrapper library.
22 * move-down
23 * File-based Hierarchical Storage Management.
24 */
25
26#include <linux/compat.h>
27#include <linux/file.h>
28#include "aufs.h"
29
30static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
31{
32 int err, fd;
33 aufs_bindex_t wbi, bindex, bbot;
34 struct file *h_file;
35 struct super_block *sb;
36 struct dentry *root;
37 struct au_branch *br;
38 struct aufs_wbr_fd wbrfd = {
39 .oflags = au_dir_roflags,
40 .brid = -1
41 };
42 const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
43 | O_NOATIME | O_CLOEXEC;
44
45 AuDebugOn(wbrfd.oflags & ~valid);
46
47 if (arg) {
48 err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
49 if (unlikely(err)) {
50 err = -EFAULT;
51 goto out;
52 }
53
54 err = -EINVAL;
55 AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
56 wbrfd.oflags |= au_dir_roflags;
57 AuDbg("0%o\n", wbrfd.oflags);
58 if (unlikely(wbrfd.oflags & ~valid))
59 goto out;
60 }
61
62 fd = get_unused_fd_flags(0);
63 err = fd;
64 if (unlikely(fd < 0))
65 goto out;
66
67 h_file = ERR_PTR(-EINVAL);
68 wbi = 0;
69 br = NULL;
70 sb = path->dentry->d_sb;
71 root = sb->s_root;
72 aufs_read_lock(root, AuLock_IR);
73 bbot = au_sbbot(sb);
74 if (wbrfd.brid >= 0) {
75 wbi = au_br_index(sb, wbrfd.brid);
76 if (unlikely(wbi < 0 || wbi > bbot))
77 goto out_unlock;
78 }
79
80 h_file = ERR_PTR(-ENOENT);
81 br = au_sbr(sb, wbi);
82 if (!au_br_writable(br->br_perm)) {
83 if (arg)
84 goto out_unlock;
85
86 bindex = wbi + 1;
87 wbi = -1;
88 for (; bindex <= bbot; bindex++) {
89 br = au_sbr(sb, bindex);
90 if (au_br_writable(br->br_perm)) {
91 wbi = bindex;
92 br = au_sbr(sb, wbi);
93 break;
94 }
95 }
96 }
97 AuDbg("wbi %d\n", wbi);
98 if (wbi >= 0)
99 h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
100 /*force_wr*/0);
101
102out_unlock:
103 aufs_read_unlock(root, AuLock_IR);
104 err = PTR_ERR(h_file);
105 if (IS_ERR(h_file))
106 goto out_fd;
107
108 au_br_put(br); /* cf. au_h_open() */
109 fd_install(fd, h_file);
110 err = fd;
111 goto out; /* success */
112
113out_fd:
114 put_unused_fd(fd);
115out:
116 AuTraceErr(err);
117 return err;
118}
119
120/* ---------------------------------------------------------------------- */
121
122long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
123{
124 long err;
125 struct dentry *dentry;
126
127 switch (cmd) {
128 case AUFS_CTL_RDU:
129 case AUFS_CTL_RDU_INO:
130 err = au_rdu_ioctl(file, cmd, arg);
131 break;
132
133 case AUFS_CTL_WBR_FD:
134 err = au_wbr_fd(&file->f_path, (void __user *)arg);
135 break;
136
137 case AUFS_CTL_IBUSY:
138 err = au_ibusy_ioctl(file, arg);
139 break;
140
141 case AUFS_CTL_BRINFO:
142 err = au_brinfo_ioctl(file, arg);
143 break;
144
145 case AUFS_CTL_FHSM_FD:
146 dentry = file->f_path.dentry;
147 if (IS_ROOT(dentry))
148 err = au_fhsm_fd(dentry->d_sb, arg);
149 else
150 err = -ENOTTY;
151 break;
152
153 default:
154 /* do not call the lower */
155 AuDbg("0x%x\n", cmd);
156 err = -ENOTTY;
157 }
158
159 AuTraceErr(err);
160 return err;
161}
162
163long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
164{
165 long err;
166
167 switch (cmd) {
168 case AUFS_CTL_MVDOWN:
169 err = au_mvdown(file->f_path.dentry, (void __user *)arg);
170 break;
171
172 case AUFS_CTL_WBR_FD:
173 err = au_wbr_fd(&file->f_path, (void __user *)arg);
174 break;
175
176 default:
177 /* do not call the lower */
178 AuDbg("0x%x\n", cmd);
179 err = -ENOTTY;
180 }
181
182 AuTraceErr(err);
183 return err;
184}
185
186#ifdef CONFIG_COMPAT
187long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
188 unsigned long arg)
189{
190 long err;
191
192 switch (cmd) {
193 case AUFS_CTL_RDU:
194 case AUFS_CTL_RDU_INO:
195 err = au_rdu_compat_ioctl(file, cmd, arg);
196 break;
197
198 case AUFS_CTL_IBUSY:
199 err = au_ibusy_compat_ioctl(file, arg);
200 break;
201
202 case AUFS_CTL_BRINFO:
203 err = au_brinfo_compat_ioctl(file, arg);
204 break;
205
206 default:
207 err = aufs_ioctl_dir(file, cmd, arg);
208 }
209
210 AuTraceErr(err);
211 return err;
212}
213
214long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
215 unsigned long arg)
216{
217 return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
218}
219#endif