2
* Copyright (C) 2008 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
20
* lookup functions for NFS branch in linux-2.6.19 and later
22
* $Id: br_nfs.c,v 1.2 2008/04/13 23:36:34 sfjro Exp $
27
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) \
28
|| !defined(CONFIG_AUFS_BR_NFS)
29
#error mis-configuraion or Makefile
32
/* ---------------------------------------------------------------------- */
34
static struct file *au_find_h_intent(struct au_hdentry *hd, struct file *file)
36
struct file *h_file, *hf;
37
struct au_hdintent *hdi, *tmp;
39
LKTRTrace("%.*s\n", AuDLNPair(hd->hd_dentry));
42
spin_lock(&hd->hd_lock);
43
list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, hdi_list) {
44
hf = hdi->hdi_file[AuIntent_BRANCH];
45
if (hdi->hdi_file[AuIntent_AUFS] == file
46
&& hf->f_dentry == hd->hd_dentry) {
48
list_del(&hdi->hdi_list);
53
spin_unlock(&hd->hd_lock);
58
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
62
struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
64
LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
65
DiMustAnyLock(dentry);
66
AuDebugOn(bindex < au_di(dentry)->di_bstart
67
|| bindex > au_di(dentry)->di_bend);
70
if (!hd->hd_intent_list || !file)
71
return h_file; /* success */
73
//AuDebugOn(au_test_wkq(current));
74
h_file = au_find_h_intent(hd, file);
79
static int au_set_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
80
struct file *file, struct file *h_file)
83
struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
84
struct au_hdintent *hdi;
87
LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
88
/* d_revalidate() holds read_lock */
89
//DiMustWriteLock(dentry);
90
AuDebugOn(bindex < au_di(dentry)->di_bstart
91
|| bindex > au_di(dentry)->di_bend
94
/* || au_test_wkq(current) */);
97
if (hd->hd_intent_list) {
99
hf = au_find_h_intent(hd, file);
102
#if 0 //def CONFIG_AUFS_DEBUG
109
AuWarn("freed hfile %.*s b%d left\n",
110
AuDLNPair(dentry), bindex);
113
spin_lock(&hd->hd_lock);
114
if (!hd->hd_intent_list) {
116
= kmalloc(sizeof(*hd->hd_intent_list),
118
if (unlikely(!hd->hd_intent_list)) {
119
spin_unlock(&hd->hd_lock);
122
INIT_LIST_HEAD(hd->hd_intent_list);
124
spin_unlock(&hd->hd_lock);
127
hdi = kmalloc(sizeof(*hdi), GFP_TEMPORARY);
132
//hdi->hdi_pid = current->pid;
133
hdi->hdi_file[AuIntent_AUFS] = file;
134
hdi->hdi_file[AuIntent_BRANCH] = h_file;
135
spin_lock(&hd->hd_lock);
136
list_add(&hdi->hdi_list, hd->hd_intent_list);
137
spin_unlock(&hd->hd_lock);
138
//AuDbgDentry(dentry);
146
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
147
aufs_bindex_t bindex, struct nameidata *nd)
158
err = au_set_h_intent(dentry, bindex, nd->intent.open.file, nd_file);
161
au_set_h_dptr(dentry, bindex, NULL);
162
//todo: update bstart and bend
170
/* ---------------------------------------------------------------------- */
172
void au_hintent_put(struct au_hdentry *hd, int do_free)
174
struct au_hdintent *hdi, *tmp;
177
if (unlikely(hd->hd_intent_list)) {
179
list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list,
181
LKTRTrace("hdi %p\n", hdi);
182
hf = hdi->hdi_file[AuIntent_BRANCH];
185
//list_del(&hdi->hdi_list);
189
kfree(hd->hd_intent_list);
193
/* ---------------------------------------------------------------------- */
196
/* subset of nameidata */
198
struct dentry *dentry;
199
struct vfsmount *mnt;
203
struct open_intent open;
207
static void au_ndsub_restore(struct nameidata *nd, struct au_ndsub *save)
209
nd->dentry = save->dentry;
211
nd->flags = save->flags;
212
nd->intent = save->intent;
216
int au_fake_intent(/* struct au_ndsub *save, */struct nameidata *nd,
221
LKTRTrace("perm %d\n", perm);
225
save->dentry = nd->dentry;
227
save->flags = nd->flags;
228
save->intent = nd->intent;
231
nd->intent.open.file = NULL;
232
if (nd->flags & LOOKUP_OPEN) {
234
nd->intent.open.file = get_empty_filp();
235
if (unlikely(!nd->intent.open.file)) {
236
//nd->intent.open.file = save->intent.open.file;
241
if (!au_br_writable(perm)) {
242
nd->intent.open.flags = au_file_roflags
243
(nd->intent.open.flags) | FMODE_READ;
244
nd->flags &= ~LOOKUP_CREATE;
253
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
254
aufs_bindex_t bindex, struct file *file)
258
LKTRTrace("nd %p, %.*s, b%d, f %d\n",
259
nd, AuDLNPair(dentry), bindex, !!file);
262
if ((nd->flags & LOOKUP_OPEN)
263
&& nd->intent.open.file
264
&& !IS_ERR(nd->intent.open.file)) {
265
if (nd->intent.open.file->f_dentry) {
266
//AuDbgFile(nd->intent.open.file);
267
err = au_set_h_intent(dentry, bindex, file,
268
nd->intent.open.file);
270
nd->intent.open.file = NULL;
272
if (unlikely(nd->intent.open.file))
273
put_filp(nd->intent.open.file);
279
#ifdef CONFIG_AUFS_DLGT
280
struct au_lookup_hash_args {
281
struct dentry **errp;
284
struct nameidata *nd;
287
static void au_call_lookup_hash(void *args)
289
struct au_lookup_hash_args *a = args;
290
*a->errp = vfsub__lookup_hash(a->name, a->base, a->nd);
293
static struct dentry *
294
au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
295
struct nameidata *nd, unsigned int flags)
297
struct dentry *dentry;
300
dirperm1 = au_ftest_ndx(flags, DIRPERM1);
301
if (!dirperm1 && !au_ftest_ndx(flags, DLGT))
302
dentry = vfsub__lookup_hash(this, parent, nd);
305
struct au_lookup_hash_args args = {
311
wkq_err = au_wkq_wait(au_call_lookup_hash, &args,
313
if (unlikely(wkq_err))
314
dentry = ERR_PTR(wkq_err);
317
AuTraceErrPtr(dentry);
321
static struct dentry *
322
au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
323
struct nameidata *nd, unsigned int flags)
325
return vfsub__lookup_hash(this, parent, nd);
327
#endif /* CONFIG_AUFS_DLGT */
329
struct dentry *au_lkup_hash(const char *name, struct dentry *parent,
330
int len, struct au_ndx *ndx)
332
struct dentry *dentry;
337
struct nameidata tmp_nd, *ndo;
340
LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
342
dentry = ERR_PTR(-EACCES);
349
hash = init_name_hash();
352
if (unlikely(c == '/' || c == '\0'))
354
hash = partial_name_hash(c, hash);
356
this.hash = end_name_hash(hash);
361
err = au_fake_intent(&tmp_nd, ndx->br->br_perm);
362
dentry = ERR_PTR(err);
366
memset(&tmp_nd, 0, sizeof(tmp_nd));
368
tmp_nd.dentry = dget(parent);
369
tmp_nd.mnt = mntget(ndx->nfsmnt);
370
dentry = au_lkup_hash_dlgt(&this, parent, &tmp_nd, ndx->flags);
371
if (0 && !IS_ERR(dentry))
373
if (!IS_ERR(dentry)) {
374
/* why negative dentry for a new dir was unhashed? */
375
if (unlikely(d_unhashed(dentry)))
377
if (tmp_nd.intent.open.file
378
&& tmp_nd.intent.open.file->f_dentry) {
379
//AuDbgFile(tmp_nd.intent.open.file);
380
ndx->nd_file = tmp_nd.intent.open.file;
381
tmp_nd.intent.open.file = NULL;
382
//au_br_get(ndx->br);
385
path_release(&tmp_nd);
388
if (tmp_nd.intent.open.file)
389
put_filp(tmp_nd.intent.open.file);
391
AuTraceErrPtr(dentry);