Commit 0f2cc4ec authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (52 commits)
  init: Open /dev/console from rootfs
  mqueue: fix typo "failues" -> "failures"
  mqueue: only set error codes if they are really necessary
  mqueue: simplify do_open() error handling
  mqueue: apply mathematics distributivity on mq_bytes calculation
  mqueue: remove unneeded info->messages initialization
  mqueue: fix mq_open() file descriptor leak on user-space processes
  fix race in d_splice_alias()
  set S_DEAD on unlink() and non-directory rename() victims
  vfs: add NOFOLLOW flag to umount(2)
  get rid of ->mnt_parent in tomoyo/realpath
  hppfs can use existing proc_mnt, no need for do_kern_mount() in there
  Mirror MS_KERNMOUNT in ->mnt_flags
  get rid of useless vfsmount_lock use in put_mnt_ns()
  Take vfsmount_lock to fs/internal.h
  get rid of insanity with namespace roots in tomoyo
  take check for new events in namespace (guts of mounts_poll()) to namespace.c
  Don't mess with generic_permission() under ->d_lock in hpfs
  sanitize const/signedness for udf
  nilfs: sanitize const/signedness in dealing with ->d_name.name
  ...

Fix up fairly trivial (famous last words...) conflicts in
drivers/infiniband/core/uverbs_main.c and security/tomoyo/realpath.c
parents 1fae4cfb 9643f5d9
......@@ -837,6 +837,9 @@ replicas continue to be exactly same.
individual lists does not affect propagation or the way propagation
tree is modified by operations.
All vfsmounts in a peer group have the same ->mnt_master. If it is
non-NULL, they form a contiguous (ordered) segment of slave list.
A example propagation tree looks as shown in the figure below.
[ NOTE: Though it looks like a forest, if we consider all the shared
mounts as a conceptual entity called 'pnode', it becomes a tree]
......@@ -874,8 +877,19 @@ replicas continue to be exactly same.
NOTE: The propagation tree is orthogonal to the mount tree.
8B Locking:
->mnt_share, ->mnt_slave, ->mnt_slave_list, ->mnt_master are protected
by namespace_sem (exclusive for modifications, shared for reading).
Normally we have ->mnt_flags modifications serialized by vfsmount_lock.
There are two exceptions: do_add_mount() and clone_mnt().
The former modifies a vfsmount that has not been visible in any shared
data structures yet.
The latter holds namespace_sem and the only references to vfsmount
are in lists that can't be traversed without namespace_sem.
8B Algorithm:
8C Algorithm:
The crux of the implementation resides in rbind/move operation.
......
......@@ -288,46 +288,30 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = HYPFS_MAGIC;
sb->s_op = &hypfs_s_ops;
if (hypfs_parse_options(data, sb)) {
rc = -EINVAL;
goto err_alloc;
}
if (hypfs_parse_options(data, sb))
return -EINVAL;
root_inode = hypfs_make_inode(sb, S_IFDIR | 0755);
if (!root_inode) {
rc = -ENOMEM;
goto err_alloc;
}
if (!root_inode)
return -ENOMEM;
root_inode->i_op = &simple_dir_inode_operations;
root_inode->i_fop = &simple_dir_operations;
root_dentry = d_alloc_root(root_inode);
sb->s_root = root_dentry = d_alloc_root(root_inode);
if (!root_dentry) {
iput(root_inode);
rc = -ENOMEM;
goto err_alloc;
return -ENOMEM;
}
if (MACHINE_IS_VM)
rc = hypfs_vm_create_files(sb, root_dentry);
else
rc = hypfs_diag_create_files(sb, root_dentry);
if (rc)
goto err_tree;
return rc;
sbi->update_file = hypfs_create_update_file(sb, root_dentry);
if (IS_ERR(sbi->update_file)) {
rc = PTR_ERR(sbi->update_file);
goto err_tree;
}
if (IS_ERR(sbi->update_file))
return PTR_ERR(sbi->update_file);
hypfs_update_update(sb);
sb->s_root = root_dentry;
pr_info("Hypervisor filesystem mounted\n");
return 0;
err_tree:
hypfs_delete_tree(root_dentry);
d_genocide(root_dentry);
dput(root_dentry);
err_alloc:
kfree(sbi);
return rc;
}
static int hypfs_get_super(struct file_system_type *fst, int flags,
......@@ -340,12 +324,12 @@ static void hypfs_kill_super(struct super_block *sb)
{
struct hypfs_sb_info *sb_info = sb->s_fs_info;
if (sb->s_root) {
if (sb->s_root)
hypfs_delete_tree(sb->s_root);
if (sb_info->update_file)
hypfs_remove(sb_info->update_file);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
}
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
kill_litter_super(sb);
}
......
......@@ -140,7 +140,7 @@ void mconsole_proc(struct mc_request *req)
goto out;
}
err = may_open(&nd.path, MAY_READ, FMODE_READ);
err = may_open(&nd.path, MAY_READ, O_RDONLY);
if (result) {
mconsole_reply(req, "Failed to open file", 1, 0);
path_put(&nd.path);
......
......@@ -146,7 +146,7 @@ extern struct idr ib_uverbs_srq_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
int is_async, int *fd);
int is_async);
struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);
void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
......
......@@ -301,10 +301,15 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
resp.num_comp_vectors = file->device->num_comp_vectors;
filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
ret = get_unused_fd();
if (ret < 0)
goto err_free;
resp.async_fd = ret;
filp = ib_uverbs_alloc_event_file(file, 1);
if (IS_ERR(filp)) {
ret = PTR_ERR(filp);
goto err_free;
goto err_fd;
}
if (copy_to_user((void __user *) (unsigned long) cmd.response,
......@@ -332,9 +337,11 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
return in_len;
err_file:
put_unused_fd(resp.async_fd);
fput(filp);
err_fd:
put_unused_fd(resp.async_fd);
err_free:
ibdev->dealloc_ucontext(ucontext);
......@@ -715,6 +722,7 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
struct ib_uverbs_create_comp_channel cmd;
struct ib_uverbs_create_comp_channel_resp resp;
struct file *filp;
int ret;
if (out_len < sizeof resp)
return -ENOSPC;
......@@ -722,9 +730,16 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
if (IS_ERR(filp))
ret = get_unused_fd();
if (ret < 0)
return ret;
resp.fd = ret;
filp = ib_uverbs_alloc_event_file(file, 0);
if (IS_ERR(filp)) {
put_unused_fd(resp.fd);
return PTR_ERR(filp);
}
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
......
......@@ -484,11 +484,10 @@ void ib_uverbs_event_handler(struct ib_event_handler *handler,
}
struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
int is_async, int *fd)
int is_async)
{
struct ib_uverbs_event_file *ev_file;
struct file *filp;
int ret;
ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
if (!ev_file)
......@@ -503,27 +502,12 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
ev_file->is_async = is_async;
ev_file->is_closed = 0;
*fd = get_unused_fd();
if (*fd < 0) {
ret = *fd;
goto err;
}
filp = anon_inode_getfile("[uverbs-event]", &uverbs_event_fops,
filp = anon_inode_getfile("[infinibandevent]", &uverbs_event_fops,
ev_file, O_RDONLY);
if (!filp) {
ret = -ENFILE;
goto err_fd;
}
if (IS_ERR(filp))
kfree(ev_file);
return filp;
err_fd:
put_unused_fd(*fd);
err:
kfree(ev_file);
return ERR_PTR(ret);
}
/*
......
......@@ -1050,7 +1050,7 @@ static void invalidate_sub(struct fsg_lun *curlun)
unsigned long rc;
rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc);
VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
}
static int do_verify(struct fsg_common *common)
......
......@@ -1448,7 +1448,7 @@ static void invalidate_sub(struct fsg_lun *curlun)
unsigned long rc;
rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc);
VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
}
static int do_verify(struct fsg_dev *fsg)
......
......@@ -60,11 +60,6 @@ do { \
current->pid, __func__, ##args); \
} while (0)
struct rehash_entry {
struct task_struct *task;
struct list_head list;
};
/* Unified info structure. This is pointed to by both the dentry and
inode structures. Each file in the filesystem has an instance of this
structure. It holds a reference to the dentry, so dentries are never
......@@ -81,7 +76,6 @@ struct autofs_info {
struct list_head active;
int active_count;
struct list_head rehash_list;
struct list_head expiring;
......@@ -104,7 +98,6 @@ struct autofs_info {
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
#define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
#define AUTOFS_INF_REHASH (1<<3) /* dentry in transit to ->lookup() */
struct autofs_wait_queue {
wait_queue_head_t queue;
......
......@@ -544,10 +544,9 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
goto out;
devid = new_encode_dev(path.mnt->mnt_sb->s_dev);
err = 0;
if (path.dentry->d_inode &&
path.mnt->mnt_root == path.dentry) {
if (path.mnt->mnt_root == path.dentry) {
err = 1;
magic = path.dentry->d_inode->i_sb->s_magic;
magic = path.mnt->mnt_sb->s_magic;
}
} else {
dev_t dev = sbi->sb->s_dev;
......@@ -560,10 +559,8 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
err = have_submounts(path.dentry);
if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) {
if (follow_down(&path))
magic = path.mnt->mnt_sb->s_magic;
}
if (follow_down(&path))
magic = path.mnt->mnt_sb->s_magic;
}
param->ismountpoint.out.devid = devid;
......
......@@ -279,7 +279,6 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
root->d_mounted--;
}
ino->flags |= AUTOFS_INF_EXPIRING;
autofs4_add_expiring(root);
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
return root;
......@@ -407,7 +406,6 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
expired, (int)expired->d_name.len, expired->d_name.name);
ino = autofs4_dentry_ino(expired);
ino->flags |= AUTOFS_INF_EXPIRING;
autofs4_add_expiring(expired);
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
spin_lock(&dcache_lock);
......@@ -435,7 +433,7 @@ int autofs4_expire_wait(struct dentry *dentry)
DPRINTK("expire done status=%d", status);
if (d_unhashed(dentry) && IS_DEADDIR(dentry->d_inode))
if (d_unhashed(dentry))
return -EAGAIN;
return status;
......@@ -475,7 +473,6 @@ int autofs4_expire_run(struct super_block *sb,
spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry);
ino->flags &= ~AUTOFS_INF_EXPIRING;
autofs4_del_expiring(dentry);
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
......@@ -506,7 +503,6 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
}
ino->flags &= ~AUTOFS_INF_EXPIRING;
autofs4_del_expiring(dentry);
complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
dput(dentry);
......
......@@ -49,7 +49,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
ino->dentry = NULL;
ino->size = 0;
INIT_LIST_HEAD(&ino->active);
INIT_LIST_HEAD(&ino->rehash_list);
ino->active_count = 0;
INIT_LIST_HEAD(&ino->expiring);
atomic_set(&ino->count, 0);
......@@ -97,63 +96,6 @@ void autofs4_free_ino(struct autofs_info *ino)
kfree(ino);
}
/*
* Deal with the infamous "Busy inodes after umount ..." message.
*
* Clean up the dentry tree. This happens with autofs if the user
* space program goes away due to a SIGKILL, SIGSEGV etc.
*/
static void autofs4_force_release(struct autofs_sb_info *sbi)
{
struct dentry *this_parent = sbi->sb->s_root;
struct list_head *next;
if (!sbi->sb->s_root)
return;
spin_lock(&dcache_lock);
repeat:
next = this_parent->d_subdirs.next;
resume:
while (next != &this_parent->d_subdirs) {
struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - don`t care */
if (!simple_positive(dentry)) {
next = next->next;
continue;
}
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
goto repeat;
}
next = next->next;
spin_unlock(&dcache_lock);
DPRINTK("dentry %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
dput(dentry);
spin_lock(&dcache_lock);
}
if (this_parent != sbi->sb->s_root) {
struct dentry *dentry = this_parent;
next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
spin_unlock(&dcache_lock);
DPRINTK("parent dentry %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
dput(dentry);
spin_lock(&dcache_lock);
goto resume;
}
spin_unlock(&dcache_lock);
}
void autofs4_kill_sb(struct super_block *sb)
{
struct autofs_sb_info *sbi = autofs4_sbi(sb);
......@@ -170,15 +112,12 @@ void autofs4_kill_sb(struct super_block *sb)
/* Free wait queues, close pipe */
autofs4_catatonic_mode(sbi);
/* Clean up and release dangling references */
autofs4_force_release(sbi);
sb->s_fs_info = NULL;
kfree(sbi);
out_kill_sb:
DPRINTK("shutting down");
kill_anon_super(sb);
kill_litter_super(sb);
}
static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
......
This diff is collapsed.
......@@ -2289,9 +2289,9 @@ cifs_oplock_break(struct slow_work *work)
if (inode && S_ISREG(inode->i_mode)) {
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (cinode->clientCanCacheAll == 0)
break_lease(inode, FMODE_READ);
break_lease(inode, O_RDONLY);
else if (cinode->clientCanCacheRead == 0)
break_lease(inode, FMODE_WRITE);
break_lease(inode, O_WRONLY);
#endif
rc = filemap_fdatawrite(inode->i_mapping);
if (cinode->clientCanCacheRead == 0) {
......
......@@ -257,6 +257,7 @@ void dput(struct dentry *dentry)
if (dentry)
goto repeat;
}
EXPORT_SYMBOL(dput);
/**
* d_invalidate - invalidate a dentry
......@@ -314,6 +315,7 @@ int d_invalidate(struct dentry * dentry)
spin_unlock(&dcache_lock);
return 0;
}
EXPORT_SYMBOL(d_invalidate);
/* This should be called _only_ with dcache_lock held */
......@@ -328,6 +330,7 @@ struct dentry * dget_locked(struct dentry *dentry)
{
return __dget_locked(dentry);
}
EXPORT_SYMBOL(dget_locked);
/**
* d_find_alias - grab a hashed alias of inode
......@@ -384,6 +387,7 @@ struct dentry * d_find_alias(struct inode *inode)
}
return de;
}
EXPORT_SYMBOL(d_find_alias);
/*
* Try to kill dentries associated with this inode.
......@@ -408,6 +412,7 @@ void d_prune_aliases(struct inode *inode)
}
spin_unlock(&dcache_lock);
}
EXPORT_SYMBOL(d_prune_aliases);
/*
* Throw away a dentry - free the inode, dput the parent. This requires that
......@@ -610,6 +615,7 @@ void shrink_dcache_sb(struct super_block * sb)
{
__shrink_dcache_sb(sb, NULL, 0);
}
EXPORT_SYMBOL(shrink_dcache_sb);
/*
* destroy a single subtree of dentries for unmount
......@@ -792,6 +798,7 @@ int have_submounts(struct dentry *parent)
spin_unlock(&dcache_lock);
return 1;
}
EXPORT_SYMBOL(have_submounts);
/*
* Search the dentry child list for the specified parent,
......@@ -876,6 +883,7 @@ void shrink_dcache_parent(struct dentry * parent)
while ((found = select_parent(parent)) != 0)
__shrink_dcache_sb(sb, &found, 0);
}
EXPORT_SYMBOL(shrink_dcache_parent);
/*
* Scan `nr' dentries and return the number which remain.
......@@ -968,6 +976,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
return dentry;
}
EXPORT_SYMBOL(d_alloc);
struct dentry *d_alloc_name(struct dentry *parent, const char *name)
{
......@@ -1012,6 +1021,7 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
spin_unlock(&dcache_lock);
security_d_instantiate(entry, inode);
}
EXPORT_SYMBOL(d_instantiate);
/**
* d_instantiate_unique - instantiate a non-aliased dentry
......@@ -1108,6 +1118,7 @@ struct dentry * d_alloc_root(struct inode * root_inode)
}
return res;
}
EXPORT_SYMBOL(d_alloc_root);
static inline struct hlist_head *d_hash(struct dentry *parent,
unsigned long hash)
......@@ -1211,7 +1222,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
spin_unlock(&dcache_lock);
security_d_instantiate(new, inode);
d_rehash(dentry);
d_move(new, dentry);
iput(inode);
} else {
......@@ -1225,6 +1235,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
d_add(dentry, inode);
return new;
}
EXPORT_SYMBOL(d_splice_alias);
/**
* d_add_ci - lookup or allocate new dentry with case-exact name
......@@ -1314,6 +1325,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
iput(inode);
return ERR_PTR(error);
}
EXPORT_SYMBOL(d_add_ci);
/**
* d_lookup - search for a dentry
......@@ -1357,6 +1369,7 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
} while (read_seqretry(&rename_lock, seq));
return dentry;
}
EXPORT_SYMBOL(d_lookup);
struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
{
......@@ -1483,6 +1496,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
out:
return 0;
}
EXPORT_SYMBOL(d_validate);
/*
* When a file is deleted, we have two options:
......@@ -1528,6 +1542,7 @@ void d_delete(struct dentry * dentry)
fsnotify_nameremove(dentry, isdir);
}
EXPORT_SYMBOL(d_delete);
static void __d_rehash(struct dentry * entry, struct hlist_head *list)
{
......@@ -1556,6 +1571,7 @@ void d_rehash(struct dentry * entry)
spin_unlock(&entry->d_lock);
spin_unlock(&dcache_lock);
}
EXPORT_SYMBOL(d_rehash);
/*
* When switching names, the actual string doesn't strictly have to
......@@ -1702,6 +1718,7 @@ void d_move(struct dentry * dentry, struct dentry * target)
d_move_locked(dentry, target);
spin_unlock(&dcache_lock);
}
EXPORT_SYMBOL(d_move);
/**
* d_ancestor - search for an ancestor
......@@ -1868,6 +1885,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
spin_unlock(&dcache_lock);
BUG();
}
EXPORT_SYMBOL_GPL(d_materialise_unique);
static int prepend(char **buffer, int *buflen, const char *str, int namelen)
{
......@@ -2005,6 +2023,7 @@ char *d_path(const struct path *path, char *buf, int buflen)
path_put(&root);
return res;
}
EXPORT_SYMBOL(d_path);
/*
* Helper function for dentry_operations.d_dname() members
......@@ -2171,6 +2190,30 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
return result;
}
int path_is_under(struct path *path1, struct path *path2)
{
struct vfsmount *mnt = path1->mnt;
struct dentry *dentry = path1->dentry;
int res;
spin_lock(&vfsmount_lock);
if (mnt != path2->mnt) {
for (;;) {
if (mnt->mnt_parent == mnt) {
spin_unlock(&vfsmount_lock);
return 0;
}
if (mnt->mnt_parent == path2->mnt)
break;
mnt = mnt->mnt_parent;
}
dentry = mnt->mnt_mountpoint;
}
res = is_subdir(dentry, path2->dentry);
spin_unlock(&vfsmount_lock);
return res;
}
EXPORT_SYMBOL(path_is_under);
void d_genocide(struct dentry *root)
{
struct dentry *this_parent = root;
......@@ -2228,6 +2271,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
}
return ino;
}
EXPORT_SYMBOL(find_inode_number);
static __initdata unsigned long dhash_entries;
static int __init set_dhash_entries(char *str)
......@@ -2297,6 +2341,7 @@ static void __init dcache_init(void)
/* SLAB cache for __getname() consumers */
struct kmem_cache *names_cachep __read_mostly;
EXPORT_SYMBOL(names_cachep);
EXPORT_SYMBOL(d_genocide);
......@@ -2326,26 +2371,3 @@ void __init vfs_caches_init(unsigned long mempages)
bdev_cache_init();
chrdev_init();
}
EXPORT_SYMBOL(d_alloc);
EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete);
EXPORT_SYMBOL(d_find_alias);
EXPORT_SYMBOL(d_instantiate);
EXPORT_SYMBOL(d_invalidate);
EXPORT_SYMBOL(d_lookup);
EXPORT_SYMBOL(d_move);
EXPORT_SYMBOL_GPL(d_materialise_unique);
EXPORT_SYMBOL(d_path);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(d_rehash);
EXPORT_SYMBOL(d_splice_alias);
EXPORT_SYMBOL(d_add_ci);
EXPORT_SYMBOL(d_validate);
EXPORT_SYMBOL(dget_locked);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(find_inode_number);
EXPORT_SYMBOL(have_submounts);
EXPORT_SYMBOL(names_cachep);
EXPORT_SYMBOL(shrink_dcache_parent);
EXPORT_SYMBOL(shrink_dcache_sb);
......@@ -496,7 +496,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
}
d_move(old_dentry, dentry);
fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
S_ISDIR(old_dentry->d_inode->i_mode),
NULL, old_dentry);
fsnotify_oldname_free(old_name);
unlock_rename(new_dir, old_dir);
......
......@@ -116,11 +116,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
* devices or filesystem images.
*/
memset(buf, 0, sizeof(buf));
path.mnt = mnt->mnt_parent;
path.dentry = mnt->mnt_mountpoint;
path_get(&path);
path.mnt = mnt;
path.dentry = mnt->mnt_root;
cp = d_path(&path, buf, sizeof(buf));
path_put(&path);
if (!IS_ERR(cp)) {
memcpy(sbi->s_es->s_last_mounted, cp,
sizeof(sbi->s_es->s_last_mounted));
......
......@@ -976,122 +976,62 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
}
/**
* gfs2_readlinki - return the contents of a symlink
* @ip: the symlink's inode
* @buf: a pointer to the buffer to be filled
* @len: a pointer to the length of @buf
* gfs2_follow_link - Follow a symbolic link
* @dentry: The dentry of the link
* @nd: Data that we pass to vfs_follow_link()
*
* If @buf is too small, a piece of memory is kmalloc()ed and needs
* to be freed by the caller.
* This can handle symlinks of any size.
*
* Returns: errno
* Returns: 0 on success or error code
*/
static int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
struct gfs2_holder i_gh;
struct buffer_head *dibh;
unsigned int x;