2 * Copyright (C) 2005-2012 Junjiro R. Okajima
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.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * readdir in userspace.
23 #include <linux/compat.h>
24 #include <linux/fs_stack.h>
25 #include <linux/security.h>
28 /* bits for struct aufs_rdu.flags */
29 #define AuRdu_CALLED 1
30 #define AuRdu_CONT (1 << 1)
31 #define AuRdu_FULL (1 << 2)
32 #define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
33 #define au_fset_rdu(flags, name) \
34 do { (flags) |= AuRdu_##name; } while (0)
35 #define au_fclr_rdu(flags, name) \
36 do { (flags) &= ~AuRdu_##name; } while (0)
40 union au_rdu_ent_ul ent;
43 struct super_block *sb;
47 static int au_rdu_fill(void *__arg, const char *name, int nlen,
48 loff_t offset, u64 h_ino, unsigned int d_type)
51 struct au_rdu_arg *arg = __arg;
52 struct aufs_rdu *rdu = arg->rdu;
53 struct au_rdu_ent ent;
57 au_fset_rdu(rdu->cookie.flags, CALLED);
58 len = au_rdu_len(nlen);
59 if (arg->ent.ul + len < arg->end) {
61 ent.bindex = rdu->cookie.bindex;
64 if (unlikely(nlen > AUFS_MAX_NAMELEN))
65 ent.type = DT_UNKNOWN;
67 /* unnecessary to support mmap_sem since this is a dir */
69 if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
71 if (copy_to_user(arg->ent.e->name, name, nlen))
73 /* the terminating NULL */
74 if (__put_user(0, arg->ent.e->name + nlen))
77 /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
82 au_fset_rdu(rdu->cookie.flags, FULL);
88 /* AuTraceErr(err); */
92 static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
96 struct au_rdu_cookie *cookie = &arg->rdu->cookie;
98 offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
100 if (unlikely(offset != cookie->h_pos))
106 au_fclr_rdu(cookie->flags, CALLED);
108 err = vfsub_readdir(h_file, au_rdu_fill, arg);
112 && au_ftest_rdu(cookie->flags, CALLED)
113 && !au_ftest_rdu(cookie->flags, FULL));
114 cookie->h_pos = h_file->f_pos;
121 static int au_rdu(struct file *file, struct aufs_rdu *rdu)
125 struct au_rdu_arg arg;
126 struct dentry *dentry;
129 struct au_rdu_cookie *cookie = &rdu->cookie;
131 err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
138 rdu->tail = rdu->ent;
142 arg.end = arg.ent.ul;
146 if (unlikely(!file->f_op || !file->f_op->readdir))
149 err = security_file_permission(file, MAY_READ);
154 dentry = file->f_dentry;
155 inode = dentry->d_inode;
157 mutex_lock(&inode->i_mutex);
159 err = mutex_lock_killable(&inode->i_mutex);
165 arg.sb = inode->i_sb;
166 err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
169 err = au_alive_dir(dentry);
176 if (unlikely(au_ftest_rdu(cookie->flags, CONT)
177 && cookie->generation != au_figen(file)))
182 rdu->blk = au_sbi(arg.sb)->si_rdblk;
184 rdu->blk = au_dir_size(file, /*dentry*/NULL);
186 bend = au_fbstart(file);
187 if (cookie->bindex < bend)
188 cookie->bindex = bend;
189 bend = au_fbend_dir(file);
190 /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
191 for (; !err && cookie->bindex <= bend;
192 cookie->bindex++, cookie->h_pos = 0) {
193 h_file = au_hf_dir(file, cookie->bindex);
197 au_fclr_rdu(cookie->flags, FULL);
198 err = au_rdu_do(h_file, &arg);
200 if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
203 AuDbg("rent %llu\n", rdu->rent);
205 if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
206 rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
207 au_fset_rdu(cookie->flags, CONT);
208 cookie->generation = au_figen(file);
211 ii_read_lock_child(inode);
212 fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
213 ii_read_unlock(inode);
216 fi_read_unlock(file);
218 si_read_unlock(arg.sb);
220 mutex_unlock(&inode->i_mutex);
226 static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
230 unsigned long long nent;
231 union au_rdu_ent_ul *u;
232 struct au_rdu_ent ent;
233 struct super_block *sb;
238 sb = file->f_dentry->d_sb;
239 si_read_lock(sb, AuLock_FLUSH);
241 /* unnecessary to support mmap_sem since this is a dir */
242 err = copy_from_user(&ent, u->e, sizeof(ent));
244 err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
251 /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
253 err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
255 err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
262 err = __put_user(ino, &u->e->ino);
268 u->ul += au_rdu_len(ent.nlen);
275 /* ---------------------------------------------------------------------- */
277 static int au_rdu_verify(struct aufs_rdu *rdu)
279 AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
280 "%llu, b%d, 0x%x, g%u}\n",
281 rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
283 rdu->rent, rdu->shwh, rdu->full,
284 rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
285 rdu->cookie.generation);
287 if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
291 rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
295 long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
299 void __user *p = (void __user *)arg;
301 err = copy_from_user(&rdu, p, sizeof(rdu));
307 err = au_rdu_verify(&rdu);
313 err = au_rdu(file, &rdu);
317 e = copy_to_user(p, &rdu, sizeof(rdu));
323 case AUFS_CTL_RDU_INO:
324 err = au_rdu_ino(file, &rdu);
338 long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
342 void __user *p = compat_ptr(arg);
344 /* todo: get_user()? */
345 err = copy_from_user(&rdu, p, sizeof(rdu));
351 rdu.ent.e = compat_ptr(rdu.ent.ul);
352 err = au_rdu_verify(&rdu);
358 err = au_rdu(file, &rdu);
362 rdu.ent.ul = ptr_to_compat(rdu.ent.e);
363 rdu.tail.ul = ptr_to_compat(rdu.tail.e);
364 e = copy_to_user(p, &rdu, sizeof(rdu));
370 case AUFS_CTL_RDU_INO:
371 err = au_rdu_ino(file, &rdu);