On Mon, 2007-05-14 at 15:10 +0530, Bharata B Rao wrote: > From: Jan Blunck <j.blunck@xxxxxxxxxxxxx> > Subject: Introduce union stack. > > Adds union stack infrastructure to the dentry structure and provides > locking routines to walk the union stack. ... > --- /dev/null > +++ b/include/linux/dcache_union.h > @@ -0,0 +1,248 @@ > +/* > + * VFS based union mount for Linux > + * > + * Copyright © 2004-2007 IBM Corporation > + * Author(s): Jan Blunck (j.blunck@xxxxxxxxxxxxx) > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the Free > + * Software Foundation; either version 2 of the License, or (at your option) > + * any later version. > + * > + */ > +#ifndef __LINUX_DCACHE_UNION_H > +#define __LINUX_DCACHE_UNION_H > +#ifdef __KERNEL__ > + > +#include <linux/union_debug.h> > +#include <linux/fs_struct.h> > +#include <asm/atomic.h> > +#include <asm/semaphore.h> > + > +#ifdef CONFIG_UNION_MOUNT > + > +/* > + * This is the union info object, that describes general information about this > + * union directory > + * > + * u_mutex protects the union stack against modification. You can reach it > + * through the d_union field in struct dentry. Hold it when you are walking > + * or modifing the union stack ! > + */ > +struct union_info { > + atomic_t u_count; > + struct mutex u_mutex; > +}; > + > +/* allocate/de-allocate */ > +extern struct union_info *union_alloc(void); > +extern struct union_info *union_get(struct union_info *); > +extern void union_put(struct union_info *); > + > +/* > + * These are the functions for locking a dentry's union. When one > + * want to acquire a denties union lock, use: > + * > + * - union_lock() when you can sleep, > + * - union_lock_spinlock() when you are holding a spinlock (that > + * you CAN savely give up and reacquire again) > + * - union_lock_readlock() when you are holding a readlock (that > + * you CAN savely give up and reacquire again) > + * > + * Otherwise get the union lock early before you enter your > + * "no sleeping here" code. > + * > + * NOTES: union_info structure is reference counted using u_count member. > + * union_get() and union_put() which get and put references on union_info > + * should be done under union_info's u_mutex. Since the last union_put() frees > + * the union_info structure itself it can't obviously be done under u_mutex. > + * union_release() should be used in such cases (Eg. dput(), umount()) where > + * union_info is disassociated from the dentries, and it becomes safe > + * to free the union_info. > + */ > +static inline void __union_lock(struct union_info *uinfo) > +{ > + BUG_ON(!atomic_read(&uinfo->u_count)); > + mutex_lock(&uinfo->u_mutex); > +} > + > +static inline void union_lock(struct dentry *dentry) > +{ > + if (unlikely(dentry && dentry->d_union)) { > + struct union_info *ui = dentry->d_union; > + > + UM_DEBUG_LOCK("\"%s\" locking %p (count=%d)\n", > + dentry->d_name.name, ui, > + atomic_read(&ui->u_count)); > + __union_lock(dentry->d_union); > + } > +} > + > +static inline void __union_unlock(struct union_info *uinfo) > +{ > + BUG_ON(!atomic_read(&uinfo->u_count)); > + mutex_unlock(&uinfo->u_mutex); > +} > + > +static inline void union_unlock(struct dentry *dentry) > +{ > + if (unlikely(dentry && dentry->d_union)) { > + struct union_info *ui = dentry->d_union; > + > + UM_DEBUG_LOCK("\"%s\" unlocking %p (count=%d)\n", > + dentry->d_name.name, ui, > + atomic_read(&ui->u_count)); > + __union_unlock(dentry->d_union); > + } > +} > + > +static inline void union_alloc_dentry(struct dentry *dentry) > +{ > + spin_lock(&dentry->d_lock); > + if (!dentry->d_union) { > + dentry->d_union = union_alloc(); > + spin_unlock(&dentry->d_lock); > + } else { > + spin_unlock(&dentry->d_lock); > + union_lock(dentry); > + } > +} > + > +static inline struct union_info *union_lock_and_get(struct dentry *dentry) > +{ > + union_lock(dentry); > + return union_get(dentry->d_union); > +} > + > +/* Shouldn't be called with last reference to union_info */ > +static inline void union_put_and_unlock(struct union_info *uinfo) > +{ > + union_put(uinfo); > + __union_unlock(&uinfo->u_mutex); ^^^^^^^^^^^^^^^^^^^ It should be __union_unlock(uinfo); Thanks, Badari - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html