2
* Copyright (C) 2005, 2006, 2007 Junjiro 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
19
/* $Id: misc.c,v 1.30 2007/04/23 00:56:45 sfjro Exp $ */
21
//#include <linux/fs.h>
22
//#include <linux/namei.h>
23
//#include <linux/mm.h>
24
//#include <asm/uaccess.h>
27
void *au_kzrealloc(void *p, int nused, int new_sz, gfp_t gfp)
31
LKTRTrace("p %p, nused %d, sz %d, ksize %d\n",
32
p, nused, new_sz, ksize(p));
33
DEBUG_ON(new_sz <= 0);
36
if (new_sz <= ksize(p)) {
37
memset(p + nused, 0, new_sz - nused);
41
q = kmalloc(new_sz, gfp);
46
memset(q + nused, 0, new_sz - nused);
52
/* ---------------------------------------------------------------------- */
54
// todo: make it inline
55
struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
56
struct super_block *sb, aufs_bindex_t bindex)
58
LKTRTrace("nd %p, b%d\n", nd, bindex);
63
fake_nd->dentry = NULL;
66
#ifndef CONFIG_AUFS_FAKE_DM
67
DiMustAnyLock(nd->dentry);
69
if (bindex <= dbend(nd->dentry))
70
fake_nd->dentry = au_h_dptr_i(nd->dentry, bindex);
71
if (fake_nd->dentry) {
72
dget(fake_nd->dentry);
73
fake_nd->mnt = sbr_mnt(sb, bindex);
74
DEBUG_ON(!fake_nd->mnt);
77
fake_nd = ERR_PTR(-ENOENT);
84
void fake_dm_release(struct nameidata *fake_nd)
86
#ifndef CONFIG_AUFS_FAKE_DM
89
dput(fake_nd->dentry);
94
/* ---------------------------------------------------------------------- */
96
int au_copy_file(struct file *dst, struct file *src, loff_t len,
97
struct super_block *sb, int *sparse)
99
int err, all_zero, dlgt;
100
unsigned long blksize;
102
/* reduce stack space */
105
LKTRTrace("%.*s, %.*s\n",
106
DLNPair(dst->f_dentry), DLNPair(src->f_dentry));
107
DEBUG_ON(!(dst->f_mode & FMODE_WRITE));
108
IMustLock(dst->f_dentry->d_parent->d_inode);
111
blksize = dst->f_dentry->d_sb->s_blocksize;
112
if (!blksize || PAGE_SIZE < blksize)
114
LKTRTrace("blksize %lu\n", blksize);
115
buf = kmalloc(blksize, GFP_KERNEL);
119
ia = kmalloc(sizeof(*ia), GFP_KERNEL);
123
dlgt = need_dlgt(sb);
125
dst->f_pos = src->f_pos = 0;
127
size_t sz, rbytes, wbytes;
131
LKTRTrace("len %lld\n", len);
136
/* support LSM and notify */
138
while (!rbytes || err == -EAGAIN || err == -EINTR)
139
err = rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
141
if (unlikely(err < 0))
145
if (len >= rbytes && rbytes == blksize) {
148
for (i = 0; all_zero && i < rbytes; i++)
156
/* support LSM and notify */
157
err = b = vfsub_write_k(dst, p, wbytes,
159
if (unlikely(err == -EAGAIN || err == -EINTR))
161
if (unlikely(err < 0))
170
err = res = vfsub_llseek(dst, rbytes, SEEK_CUR);
171
if (unlikely(res < 0))
178
/* the last block may be a hole */
179
if (unlikely(!err && all_zero)) {
180
struct dentry *h_d = dst->f_dentry;
181
struct inode *h_i = h_d->d_inode;
183
LKTRLabel(last hole);
185
err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, dlgt);
186
} while (err == -EAGAIN || err == -EINTR);
188
ia->ia_size = dst->f_pos;
189
ia->ia_valid = ATTR_SIZE | ATTR_FILE;
192
err = vfsub_notify_change(h_d, ia, dlgt);
205
/* ---------------------------------------------------------------------- */
207
int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode)
211
err = br_rdonly(stobr(sb, bindex));
213
struct inode *hi = au_h_iptr_i(inode, bindex);
215
err = IS_IMMUTABLE(hi) ? -EROFS : 0;
220
int au_test_perm(struct inode *hidden_inode, int mask, int dlgt)
224
if (unlikely(au_is_nfs(hidden_inode->i_sb)
225
&& (mask & MAY_WRITE)
226
&& S_ISDIR(hidden_inode->i_mode)))
227
mask |= MAY_READ; /* force permission check */
228
return vfsub_permission(hidden_inode, mask, NULL, dlgt);