Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Mar 2010 16:15:33 +0000 (08:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Mar 2010 16:15:33 +0000 (08:15 -0800)
* '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

73 files changed:
Documentation/filesystems/sharedsubtree.txt
arch/s390/hypfs/inode.c
arch/um/drivers/mconsole_kern.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/file_storage.c
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/cifs/file.c
fs/dcache.c
fs/debugfs/inode.c
fs/ext4/file.c
fs/gfs2/ops_inode.c
fs/hpfs/anode.c
fs/hpfs/dentry.c
fs/hpfs/dir.c
fs/hpfs/dnode.c
fs/hpfs/ea.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/map.c
fs/hpfs/name.c
fs/hpfs/namei.c
fs/hppfs/hppfs.c
fs/internal.h
fs/libfs.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfs/inode.c
fs/nfs/nfs4proc.c
fs/nfsctl.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/nilfs2/dir.c
fs/nilfs2/namei.c
fs/nilfs2/nilfs.h
fs/notify/inotify/inotify_user.c
fs/open.c
fs/pnode.c
fs/pnode.h
fs/proc/base.c
fs/proc/generic.c
fs/proc/root.c
fs/super.c
fs/udf/balloc.c
fs/udf/dir.c
fs/udf/inode.c
fs/udf/namei.c
fs/udf/symlink.c
fs/ufs/dir.c
fs/ufs/ufs.h
include/linux/audit.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/magic.h
include/linux/mnt_namespace.h
include/linux/mount.h
init/do_mounts_initrd.c
init/main.c
ipc/mqueue.c
kernel/audit_tree.c
kernel/auditsc.c
kernel/sysctl_binary.c
mm/filemap.c
net/sunrpc/rpc_pipe.c
security/smack/smack_lsm.c
security/tomoyo/realpath.c

index 23a181074f94b5f65ac25c603d65fc749fa5ed78..fc0e39af43c32a42343f97daed5a5d285f844863 100644 (file)
@@ -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.
 
index 341aff2687a5f7453781d3483462e1e4b9c2863a..cd128b07beda7e1c798043c984d4343aa06ae046 100644 (file)
@@ -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);
 }
 
index 3b3c36601a7b39e3634458eb11c5b0245261cb3e..de317d0c329486b57efb3568f7c4514393ac5677 100644 (file)
@@ -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);
index e54d9ac6d1cabee6a14e25dc5ce94939d5d2910e..a078e5624d22f700c0a526538e6e2926f5d2775f 100644 (file)
@@ -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,
index 112d3970222a08c3ea43af3aeeb4c9977c5546ff..f71cf138d674109c6d3f10381f64d4ffcb8c5358 100644 (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)) {
index ff59a795e840f7665f8e0b8fca5fdd5b06a31e57..4fa2e65164418e033e36065baeec38d74db32032 100644 (file)
@@ -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);
 }
 
 /*
index b1935fe156a0320769481cf6419c4d58286c52bc..5a3cdd08f1d05c7d589399670fa2ac4eec7eb4a7 100644 (file)
@@ -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)
index a90dd2db04889aa5b20fa0f938d367c8cf31c9c7..b49d86e3e45b639d2d3f4760d027e38a0fd52d44 100644 (file)
@@ -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)
index 0118d67221b218672c622fdd1927289c1d9459ed..3d283abf67d7bb0aae5affddee58fdf504706df1 100644 (file)
@@ -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;
index 00bf8fcb245f13cfd7bab5fcd7bc0fdb92952087..c8a80dffb4557d80999b71c66b94cb4a7d2b75fe 100644 (file)
@@ -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;
index 74bc9aa6df310d4ccdf0d312dd43976c02f93d1e..a796c9417fb16f5b4b27ce56586753d3c5b7e948 100644 (file)
@@ -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 @@ found:
                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);
index d0a3de247458aae03f045bf6788b64e5045ad950..821b2b955dac2c7b847a91d7abc91d4e0162c838 100644 (file)
@@ -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)
index 30cc9ddf4b708454c772ca95fc848c5c83ca92df..a015b49891df6347f70f6c318666b63a74638dc8 100644 (file)
@@ -104,99 +104,6 @@ static void autofs4_del_active(struct dentry *dentry)
        return;
 }
 
-static void autofs4_add_rehash_entry(struct autofs_info *ino,
-                                    struct rehash_entry *entry)
-{
-       entry->task = current;
-       INIT_LIST_HEAD(&entry->list);
-       list_add(&entry->list, &ino->rehash_list);
-       return;
-}
-
-static void autofs4_remove_rehash_entry(struct autofs_info *ino)
-{
-       struct list_head *head = &ino->rehash_list;
-       struct rehash_entry *entry;
-       list_for_each_entry(entry, head, list) {
-               if (entry->task == current) {
-                       list_del(&entry->list);
-                       kfree(entry);
-                       break;
-               }
-       }
-       return;
-}
-
-static void autofs4_remove_rehash_entrys(struct autofs_info *ino)
-{
-       struct autofs_sb_info *sbi = ino->sbi;
-       struct rehash_entry *entry, *next;
-       struct list_head *head;
-
-       spin_lock(&sbi->fs_lock);
-       spin_lock(&sbi->lookup_lock);
-       if (!(ino->flags & AUTOFS_INF_REHASH)) {
-               spin_unlock(&sbi->lookup_lock);
-               spin_unlock(&sbi->fs_lock);
-               return;
-       }
-       ino->flags &= ~AUTOFS_INF_REHASH;
-       head = &ino->rehash_list;
-       list_for_each_entry_safe(entry, next, head, list) {
-               list_del(&entry->list);
-               kfree(entry);
-       }
-       spin_unlock(&sbi->lookup_lock);
-       spin_unlock(&sbi->fs_lock);
-       dput(ino->dentry);
-
-       return;
-}
-
-static void autofs4_revalidate_drop(struct dentry *dentry,
-                                   struct rehash_entry *entry)
-{
-       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
-       /*
-        * Add to the active list so we can pick this up in
-        * ->lookup(). Also add an entry to a rehash list so
-        * we know when there are no dentrys in flight so we
-        * know when we can rehash the dentry.
-        */
-       spin_lock(&sbi->lookup_lock);
-       if (list_empty(&ino->active))
-               list_add(&ino->active, &sbi->active_list);
-       autofs4_add_rehash_entry(ino, entry);
-       spin_unlock(&sbi->lookup_lock);
-       if (!(ino->flags & AUTOFS_INF_REHASH)) {
-               ino->flags |= AUTOFS_INF_REHASH;
-               dget(dentry);
-               spin_lock(&dentry->d_lock);
-               __d_drop(dentry);
-               spin_unlock(&dentry->d_lock);
-       }
-       return;
-}
-
-static void autofs4_revalidate_rehash(struct dentry *dentry)
-{
-       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
-       if (ino->flags & AUTOFS_INF_REHASH) {
-               spin_lock(&sbi->lookup_lock);
-               autofs4_remove_rehash_entry(ino);
-               if (list_empty(&ino->rehash_list)) {
-                       spin_unlock(&sbi->lookup_lock);
-                       ino->flags &= ~AUTOFS_INF_REHASH;
-                       d_rehash(dentry);
-                       dput(ino->dentry);
-               } else
-                       spin_unlock(&sbi->lookup_lock);
-       }
-       return;
-}
-
 static unsigned int autofs4_need_mount(unsigned int flags)
 {
        unsigned int res = 0;
@@ -236,7 +143,7 @@ out:
        return dcache_dir_open(inode, file);
 }
 
-static int try_to_fill_dentry(struct dentry *dentry)
+static int try_to_fill_dentry(struct dentry *dentry, int flags)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
@@ -249,17 +156,55 @@ static int try_to_fill_dentry(struct dentry *dentry)
         * Wait for a pending mount, triggering one if there
         * isn't one already
         */
-       DPRINTK("waiting for mount name=%.*s",
-                dentry->d_name.len, dentry->d_name.name);
+       if (dentry->d_inode == NULL) {
+               DPRINTK("waiting for mount name=%.*s",
+                        dentry->d_name.len, dentry->d_name.name);
 
-       status = autofs4_wait(sbi, dentry, NFY_MOUNT);
+               status = autofs4_wait(sbi, dentry, NFY_MOUNT);
 
-       DPRINTK("mount done status=%d", status);
+               DPRINTK("mount done status=%d", status);
 
-       /* Update expiry counter */
-       ino->last_used = jiffies;
+               /* Turn this into a real negative dentry? */
+               if (status == -ENOENT) {
+                       spin_lock(&sbi->fs_lock);
+                       ino->flags &= ~AUTOFS_INF_PENDING;
+                       spin_unlock(&sbi->fs_lock);
+                       return status;
+               } else if (status) {
+                       /* Return a negative dentry, but leave it "pending" */
+                       return status;
+               }
+       /* Trigger mount for path component or follow link */
+       } else if (ino->flags & AUTOFS_INF_PENDING ||
+                       autofs4_need_mount(flags) ||
+                       current->link_count) {
+               DPRINTK("waiting for mount name=%.*s",
+                       dentry->d_name.len, dentry->d_name.name);
 
-       return status;
+               spin_lock(&sbi->fs_lock);
+               ino->flags |= AUTOFS_INF_PENDING;
+               spin_unlock(&sbi->fs_lock);
+               status = autofs4_wait(sbi, dentry, NFY_MOUNT);
+
+               DPRINTK("mount done status=%d", status);
+
+               if (status) {
+                       spin_lock(&sbi->fs_lock);
+                       ino->flags &= ~AUTOFS_INF_PENDING;
+                       spin_unlock(&sbi->fs_lock);
+                       return status;
+               }
+       }
+
+       /* Initialize expiry counter after successful mount */
+       if (ino)
+               ino->last_used = jiffies;
+
+       spin_lock(&sbi->fs_lock);
+       ino->flags &= ~AUTOFS_INF_PENDING;
+       spin_unlock(&sbi->fs_lock);
+
+       return 0;
 }
 
 /* For autofs direct mounts the follow link triggers the mount */
@@ -313,16 +258,10 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
         */
        if (ino->flags & AUTOFS_INF_PENDING ||
            (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
-               ino->flags |= AUTOFS_INF_PENDING;
                spin_unlock(&dcache_lock);
                spin_unlock(&sbi->fs_lock);
 
-               status = try_to_fill_dentry(dentry);
-
-               spin_lock(&sbi->fs_lock);
-               ino->flags &= ~AUTOFS_INF_PENDING;
-               spin_unlock(&sbi->fs_lock);
-
+               status = try_to_fill_dentry(dentry, 0);
                if (status)
                        goto out_error;
 
@@ -361,47 +300,18 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *dir = dentry->d_parent->d_inode;
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
-       struct rehash_entry *entry;
+       int oz_mode = autofs4_oz_mode(sbi);
        int flags = nd ? nd->flags : 0;
-       unsigned int mutex_aquired;
+       int status = 1;
 
-       DPRINTK("name = %.*s oz_mode = %d",
-               dentry->d_name.len, dentry->d_name.name, oz_mode);
-
-       /* Daemon never causes a mount to trigger */
-       if (autofs4_oz_mode(sbi))
-               return 1;
-
-       entry = kmalloc(sizeof(struct rehash_entry), GFP_KERNEL);
-       if (!entry)
-               return -ENOMEM;
-
-       mutex_aquired = mutex_trylock(&dir->i_mutex);
-
-       spin_lock(&sbi->fs_lock);
-       spin_lock(&dcache_lock);
        /* Pending dentry */
+       spin_lock(&sbi->fs_lock);
        if (autofs4_ispending(dentry)) {
-               int status;
-
-               /*
-                * We can only unhash and send this to ->lookup() if
-                * the directory mutex is held over d_revalidate() and
-                * ->lookup(). This prevents the VFS from incorrectly
-                * seeing the dentry as non-existent.
-                */
-               ino->flags |= AUTOFS_INF_PENDING;
-               if (!mutex_aquired) {
-                       autofs4_revalidate_drop(dentry, entry);
-                       spin_unlock(&dcache_lock);
-                       spin_unlock(&sbi->fs_lock);
-                       return 0;
-               }
-               spin_unlock(&dcache_lock);
+               /* The daemon never causes a mount to trigger */
                spin_unlock(&sbi->fs_lock);
-               mutex_unlock(&dir->i_mutex);
-               kfree(entry);
+
+               if (oz_mode)
+                       return 1;
 
                /*
                 * If the directory has gone away due to an expire
@@ -415,82 +325,45 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
                 * A zero status is success otherwise we have a
                 * negative error code.
                 */
-               status = try_to_fill_dentry(dentry);
-
-               spin_lock(&sbi->fs_lock);
-               ino->flags &= ~AUTOFS_INF_PENDING;
-               spin_unlock(&sbi->fs_lock);
-
+               status = try_to_fill_dentry(dentry, flags);
                if (status == 0)
                        return 1;
 
                return status;
        }
+       spin_unlock(&sbi->fs_lock);
+
+       /* Negative dentry.. invalidate if "old" */
+       if (dentry->d_inode == NULL)
+               return 0;
 
        /* Check for a non-mountpoint directory with no contents */
+       spin_lock(&dcache_lock);
        if (S_ISDIR(dentry->d_inode->i_mode) &&
            !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
                DPRINTK("dentry=%p %.*s, emptydir",
                         dentry, dentry->d_name.len, dentry->d_name.name);
+               spin_unlock(&dcache_lock);
 
-               if (autofs4_need_mount(flags) || current->link_count) {
-                       int status;
-
-                       /*
-                        * We can only unhash and send this to ->lookup() if
-                        * the directory mutex is held over d_revalidate() and
-                        * ->lookup(). This prevents the VFS from incorrectly
-                        * seeing the dentry as non-existent.
-                        */
-                       ino->flags |= AUTOFS_INF_PENDING;
-                       if (!mutex_aquired) {
-                               autofs4_revalidate_drop(dentry, entry);
-                               spin_unlock(&dcache_lock);
-                               spin_unlock(&sbi->fs_lock);
-                               return 0;
-                       }
-                       spin_unlock(&dcache_lock);
-                       spin_unlock(&sbi->fs_lock);
-                       mutex_unlock(&dir->i_mutex);
-                       kfree(entry);
-
-                       /*
-                        * A zero status is success otherwise we have a
-                        * negative error code.
-                        */
-                       status = try_to_fill_dentry(dentry);
-
-                       spin_lock(&sbi->fs_lock);
-                       ino->flags &= ~AUTOFS_INF_PENDING;
-                       spin_unlock(&sbi->fs_lock);
+               /* The daemon never causes a mount to trigger */
+               if (oz_mode)
+                       return 1;
 
-                       if (status == 0)
-                               return 1;
+               /*
+                * A zero status is success otherwise we have a
+                * negative error code.
+                */
+               status = try_to_fill_dentry(dentry, flags);
+               if (status == 0)
+                       return 1;
 
-                       return status;
-               }
+               return status;
        }
        spin_unlock(&dcache_lock);
-       spin_unlock(&sbi->fs_lock);
-
-       if (mutex_aquired)
-               mutex_unlock(&dir->i_mutex);
-
-       kfree(entry);
 
        return 1;
 }
 
-static void autofs4_free_rehash_entrys(struct autofs_info *inf)
-{
-       struct list_head *head = &inf->rehash_list;
-       struct rehash_entry *entry, *next;
-       list_for_each_entry_safe(entry, next, head, list) {
-               list_del(&entry->list);
-               kfree(entry);
-       }
-}
-
 void autofs4_dentry_release(struct dentry *de)
 {
        struct autofs_info *inf;
@@ -509,8 +382,6 @@ void autofs4_dentry_release(struct dentry *de)
                                list_del(&inf->active);
                        if (!list_empty(&inf->expiring))
                                list_del(&inf->expiring);
-                       if (!list_empty(&inf->rehash_list))
-                               autofs4_free_rehash_entrys(inf);
                        spin_unlock(&sbi->lookup_lock);
                }
 
@@ -543,7 +414,6 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
        const unsigned char *str = name->name;
        struct list_head *p, *head;
 
-restart:
        spin_lock(&dcache_lock);
        spin_lock(&sbi->lookup_lock);
        head = &sbi->active_list;
@@ -561,19 +431,6 @@ restart:
                if (atomic_read(&active->d_count) == 0)
                        goto next;
 
-               if (active->d_inode && IS_DEADDIR(active->d_inode)) {
-                       if (!list_empty(&ino->rehash_list)) {
-                               dget(active);
-                               spin_unlock(&active->d_lock);
-                               spin_unlock(&sbi->lookup_lock);
-                               spin_unlock(&dcache_lock);
-                               autofs4_remove_rehash_entrys(ino);
-                               dput(active);
-                               goto restart;
-                       }
-                       goto next;
-               }
-
                qstr = &active->d_name;
 
                if (active->d_name.hash != hash)
@@ -586,11 +443,13 @@ restart:
                if (memcmp(qstr->name, str, len))
                        goto next;
 
-               dget(active);
-               spin_unlock(&active->d_lock);
-               spin_unlock(&sbi->lookup_lock);
-               spin_unlock(&dcache_lock);
-               return active;
+               if (d_unhashed(active)) {
+                       dget(active);
+                       spin_unlock(&active->d_lock);
+                       spin_unlock(&sbi->lookup_lock);
+                       spin_unlock(&dcache_lock);
+                       return active;
+               }
 next:
                spin_unlock(&active->d_lock);
        }
@@ -639,11 +498,13 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
                if (memcmp(qstr->name, str, len))
                        goto next;
 
-               dget(expiring);
-               spin_unlock(&expiring->d_lock);
-               spin_unlock(&sbi->lookup_lock);
-               spin_unlock(&dcache_lock);
-               return expiring;
+               if (d_unhashed(expiring)) {
+                       dget(expiring);
+                       spin_unlock(&expiring->d_lock);
+                       spin_unlock(&sbi->lookup_lock);
+                       spin_unlock(&dcache_lock);
+                       return expiring;
+               }
 next:
                spin_unlock(&expiring->d_lock);
        }
@@ -653,48 +514,6 @@ next:
        return NULL;
 }
 
-static struct autofs_info *init_new_dentry(struct autofs_sb_info *sbi,
-                                          struct dentry *dentry, int oz_mode)
-{
-       struct autofs_info *ino;
-
-       /*
-        * Mark the dentry incomplete but don't hash it. We do this
-        * to serialize our inode creation operations (symlink and
-        * mkdir) which prevents deadlock during the callback to
-        * the daemon. Subsequent user space lookups for the same
-        * dentry are placed on the wait queue while the daemon
-        * itself is allowed passage unresticted so the create
-        * operation itself can then hash the dentry. Finally,
-        * we check for the hashed dentry and return the newly
-        * hashed dentry.
-        */
-       dentry->d_op = &autofs4_root_dentry_operations;
-
-       /*
-        * And we need to ensure that the same dentry is used for
-        * all following lookup calls until it is hashed so that
-        * the dentry flags are persistent throughout the request.
-        */
-       ino = autofs4_init_ino(NULL, sbi, 0555);
-       if (!ino)
-               return ERR_PTR(-ENOMEM);
-
-       dentry->d_fsdata = ino;
-       ino->dentry = dentry;
-
-       /*
-        * Only set the mount pending flag for new dentrys not created
-        * by the daemon.
-        */
-       if (!oz_mode)
-               ino->flags |= AUTOFS_INF_PENDING;
-
-       d_instantiate(dentry, NULL);
-
-       return ino;
-}
-
 /* Lookups in the root directory */
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
@@ -702,7 +521,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
        struct autofs_info *ino;
        struct dentry *expiring, *active;
        int oz_mode;
-       int status = 0;
 
        DPRINTK("name = %.*s",
                dentry->d_name.len, dentry->d_name.name);
@@ -717,26 +535,44 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
        DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
                 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
 
-       spin_lock(&sbi->fs_lock);
        active = autofs4_lookup_active(dentry);
        if (active) {
                dentry = active;
                ino = autofs4_dentry_ino(dentry);
-               /* If this came from revalidate, rehash it */
-               autofs4_revalidate_rehash(dentry);
-               spin_unlock(&sbi->fs_lock);
        } else {
-               spin_unlock(&sbi->fs_lock);
-               ino = init_new_dentry(sbi, dentry, oz_mode);
-               if (IS_ERR(ino))
-                       return (struct dentry *) ino;
-       }
+               /*
+                * Mark the dentry incomplete but don't hash it. We do this
+                * to serialize our inode creation operations (symlink and
+                * mkdir) which prevents deadlock during the callback to
+                * the daemon. Subsequent user space lookups for the same
+                * dentry are placed on the wait queue while the daemon
+                * itself is allowed passage unresticted so the create
+                * operation itself can then hash the dentry. Finally,
+                * we check for the hashed dentry and return the newly
+                * hashed dentry.
+                */
+               dentry->d_op = &autofs4_root_dentry_operations;
+
+               /*
+                * And we need to ensure that the same dentry is used for
+                * all following lookup calls until it is hashed so that
+                * the dentry flags are persistent throughout the request.
+                */
+               ino = autofs4_init_ino(NULL, sbi, 0555);
+               if (!ino)
+                       return ERR_PTR(-ENOMEM);
 
-       autofs4_add_active(dentry);
+               dentry->d_fsdata = ino;
+               ino->dentry = dentry;
+
+               autofs4_add_active(dentry);
+
+               d_instantiate(dentry, NULL);
+       }
 
        if (!oz_mode) {
-               expiring = autofs4_lookup_expiring(dentry);
                mutex_unlock(&dir->i_mutex);
+               expiring = autofs4_lookup_expiring(dentry);
                if (expiring) {
                        /*
                         * If we are racing with expire the request might not
@@ -744,22 +580,23 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
                         * so it must have been successful, so just wait for it.
                         */
                        autofs4_expire_wait(expiring);
+                       autofs4_del_expiring(expiring);
                        dput(expiring);
                }
-               status = try_to_fill_dentry(dentry);
-               mutex_lock(&dir->i_mutex);
+
                spin_lock(&sbi->fs_lock);
-               ino->flags &= ~AUTOFS_INF_PENDING;
+               ino->flags |= AUTOFS_INF_PENDING;
                spin_unlock(&sbi->fs_lock);
+               if (dentry->d_op && dentry->d_op->d_revalidate)
+                       (dentry->d_op->d_revalidate)(dentry, nd);
+               mutex_lock(&dir->i_mutex);
        }
 
-       autofs4_del_active(dentry);
-
        /*
-        * If we had a mount fail, check if we had to handle
+        * If we are still pending, check if we had to handle
         * a signal. If so we can force a restart..
         */
-       if (status) {
+       if (ino->flags & AUTOFS_INF_PENDING) {
                /* See if we were interrupted */
                if (signal_pending(current)) {
                        sigset_t *sigset = &current->pending.signal;
@@ -771,46 +608,43 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
                            return ERR_PTR(-ERESTARTNOINTR);
                        }
                }
-       }
-
-       /*
-        * User space can (and has done in the past) remove and re-create
-        * this directory during the callback. This can leave us with an
-        * unhashed dentry, but a successful mount!  So we need to
-        * perform another cached lookup in case the dentry now exists.
-        */
-       if (!oz_mode && !have_submounts(dentry)) {
-               struct dentry *new;
-               new = d_lookup(dentry->d_parent, &dentry->d_name);
-               if (new) {
-                       if (active)
-                               dput(active);
-                       return new;
-               } else {
-                       if (!status)
-                               status = -ENOENT;
+               if (!oz_mode) {
+                       spin_lock(&sbi->fs_lock);
+                       ino->flags &= ~AUTOFS_INF_PENDING;
+                       spin_unlock(&sbi->fs_lock);
                }
        }
 
        /*
-        * If we had a mount failure, return status to user space.
-        * If the mount succeeded and we used a dentry from the active queue
-        * return it.
+        * If this dentry is unhashed, then we shouldn't honour this
+        * lookup.  Returning ENOENT here doesn't do the right thing
+        * for all system calls, but it should be OK for the operations
+        * we permit from an autofs.
         */
-       if (status) {
-               dentry = ERR_PTR(status);
-               if (active)
-                       dput(active);
-               return dentry;
-       } else {
+       if (!oz_mode && d_unhashed(dentry)) {
                /*
-                * Valid successful mount, return active dentry or NULL
-                * for a new dentry.
+                * A user space application can (and has done in the past)
+                * remove and re-create this directory during the callback.
+                * This can leave us with an unhashed dentry, but a
+                * successful mount!  So we need to perform another
+                * cached lookup in case the dentry now exists.
                 */
+               struct dentry *parent = dentry->d_parent;
+               struct dentry *new = d_lookup(parent, &dentry->d_name);
+               if (new != NULL)
+                       dentry = new;
+               else
+                       dentry = ERR_PTR(-ENOENT);
+
                if (active)
-                       return active;
+                       dput(active);
+
+               return dentry;
        }
 
+       if (active)
+               return active;
+
        return NULL;
 }
 
@@ -834,6 +668,8 @@ static int autofs4_dir_symlink(struct inode *dir,
        if (!ino)
                return -ENOMEM;
 
+       autofs4_del_active(dentry);
+
        ino->size = strlen(symname);
        cp = kmalloc(ino->size + 1, GFP_KERNEL);
        if (!cp) {
@@ -910,6 +746,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
        dir->i_mtime = CURRENT_TIME;
 
        spin_lock(&dcache_lock);
+       autofs4_add_expiring(dentry);
        spin_lock(&dentry->d_lock);
        __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
@@ -935,6 +772,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
                spin_unlock(&dcache_lock);
                return -ENOTEMPTY;
        }
+       autofs4_add_expiring(dentry);
        spin_lock(&dentry->d_lock);
        __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
@@ -972,6 +810,8 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (!ino)
                return -ENOMEM;
 
+       autofs4_del_active(dentry);
+
        inode = autofs4_get_inode(dir->i_sb, ino);
        if (!inode) {
                if (!dentry->d_fsdata)
index 057e1dae12ab521a98f356a814fd303b99624776..3d8f8a96f5a350a96e732cc65f45bc843ab6f08e 100644 (file)
@@ -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) {
index 953173a293a93e3d8174e7d5955a70f535a75fb5..f1358e5c3a59b3b5f2551980956f84e09355378e 100644 (file)
@@ -257,6 +257,7 @@ kill_it:
        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 @@ restart:
        }
        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 @@ positive:
        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 @@ err_out:
        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 @@ shouldnt_be_hashed:
        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);
index 274ac865bae8c776180bc28a19d589f902a090c0..049d6c36da0992eb0e7bbf1938ff5ff2a8d35156 100644 (file)
@@ -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);
index 9630583cef280d541e87505eba2cfa37589266e3..56eee3d796c2e7122e84e99e957ac7ff5cbd2dfd 100644 (file)
@@ -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));
index 84350e1be66d2b286e306b13395953557ace4be8..4e64352d49de1b442c5d627eb4ce3adba8c94f92 100644 (file)
@@ -976,122 +976,62 @@ out:
 }
 
 /**
- * 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;
+       char *buf;
        int error;
 
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
        error = gfs2_glock_nq(&i_gh);
        if (error) {
                gfs2_holder_uninit(&i_gh);
-               return error;
+               nd_set_link(nd, ERR_PTR(error));
+               return NULL;
        }
 
        if (!ip->i_disksize) {
                gfs2_consist_inode(ip);
-               error = -EIO;
+               buf = ERR_PTR(-EIO);
                goto out;
        }
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
-       if (error)
+       if (error) {
+               buf = ERR_PTR(error);
                goto out;
-
-       x = ip->i_disksize + 1;
-       if (x > *len) {
-               *buf = kmalloc(x, GFP_NOFS);
-               if (!*buf) {
-                       error = -ENOMEM;
-                       goto out_brelse;
-               }
        }
 
-       memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
-       *len = x;
-
-out_brelse:
+       x = ip->i_disksize + 1;
+       buf = kmalloc(x, GFP_NOFS);
+       if (!buf)
+               buf = ERR_PTR(-ENOMEM);
+       else
+               memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
        brelse(dibh);
 out:
        gfs2_glock_dq_uninit(&i_gh);
-       return error;
-}
-
-/**
- * gfs2_readlink - Read the value of a symlink
- * @dentry: the symlink
- * @buf: the buffer to read the symlink data into
- * @size: the size of the buffer
- *
- * Returns: errno
- */
-
-static int gfs2_readlink(struct dentry *dentry, char __user *user_buf,
-                        int user_size)
-{
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       char array[GFS2_FAST_NAME_SIZE], *buf = array;
-       unsigned int len = GFS2_FAST_NAME_SIZE;
-       int error;
-
-       error = gfs2_readlinki(ip, &buf, &len);
-       if (error)
-               return error;
-
-       if (user_size > len - 1)
-               user_size = len - 1;
-
-       if (copy_to_user(user_buf, buf, user_size))
-               error = -EFAULT;
-       else
-               error = user_size;
-
-       if (buf != array)
-               kfree(buf);
-
-       return error;
+       nd_set_link(nd, buf);
+       return NULL;
 }
 
-/**
- * gfs2_follow_link - Follow a symbolic link
- * @dentry: The dentry of the link
- * @nd: Data that we pass to vfs_follow_link()
- *
- * This can handle symlinks of any size. It is optimised for symlinks
- * under GFS2_FAST_NAME_SIZE.
- *
- * Returns: 0 on success or error code
- */
-
-static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       char array[GFS2_FAST_NAME_SIZE], *buf = array;
-       unsigned int len = GFS2_FAST_NAME_SIZE;
-       int error;
-
-       error = gfs2_readlinki(ip, &buf, &len);
-       if (!error) {
-               error = vfs_follow_link(nd, buf);
-               if (buf != array)
-                       kfree(buf);
-       } else
-               path_put(&nd->path);
-
-       return ERR_PTR(error);
+       char *s = nd_get_link(nd);
+       if (!IS_ERR(s))
+               kfree(s);
 }
 
 /**
@@ -1426,8 +1366,9 @@ const struct inode_operations gfs2_dir_iops = {
 };
 
 const struct inode_operations gfs2_symlink_iops = {
-       .readlink = gfs2_readlink,
+       .readlink = generic_readlink,
        .follow_link = gfs2_follow_link,
+       .put_link = gfs2_put_link,
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
index 1aa88c4e0964b5acad9f37c3928167406493e564..6a2f04bf3df007249047523e10a098fd2b43c603 100644 (file)
@@ -353,7 +353,7 @@ int hpfs_ea_read(struct super_block *s, secno a, int ano, unsigned pos,
 }
 
 int hpfs_ea_write(struct super_block *s, secno a, int ano, unsigned pos,
-            unsigned len, char *buf)
+            unsigned len, const char *buf)
 {
        struct buffer_head *bh;
        char *data;
index 940d6d150beec4d609785c16aadb87a49b1689f7..67d9d36b3d5fa05534b0a0abe320da25292e839d 100644 (file)
@@ -20,8 +20,8 @@ static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
 
        if (l == 1) if (qstr->name[0]=='.') goto x;
        if (l == 2) if (qstr->name[0]=='.' || qstr->name[1]=='.') goto x;
-       hpfs_adjust_length((char *)qstr->name, &l);
-       /*if (hpfs_chk_name((char *)qstr->name,&l))*/
+       hpfs_adjust_length(qstr->name, &l);
+       /*if (hpfs_chk_name(qstr->name,&l))*/
                /*return -ENAMETOOLONG;*/
                /*return -ENOENT;*/
        x:
@@ -38,14 +38,16 @@ static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qst
 {
        unsigned al=a->len;
        unsigned bl=b->len;
-       hpfs_adjust_length((char *)a->name, &al);
-       /*hpfs_adjust_length((char *)b->name, &bl);*/
+       hpfs_adjust_length(a->name, &al);
+       /*hpfs_adjust_length(b->name, &bl);*/
        /* 'a' is the qstr of an already existing dentry, so the name
         * must be valid. 'b' must be validated first.
         */
 
-       if (hpfs_chk_name((char *)b->name, &bl)) return 1;
-       if (hpfs_compare_names(dentry->d_sb, (char *)a->name, al, (char *)b->name, bl, 0)) return 1;
+       if (hpfs_chk_name(b->name, &bl))
+               return 1;
+       if (hpfs_compare_names(dentry->d_sb, a->name, al, b->name, bl, 0))
+               return 1;
        return 0;
 }
 
index 8865c94f55f602f19cb3b68182fc70bd41fcb4e4..26e3964a4b8c19a7075d0ef623ab041392c78b53 100644 (file)
@@ -59,7 +59,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct hpfs_dirent *de;
        int lc;
        long old_pos;
-       char *tempname;
+       unsigned char *tempname;
        int c1, c2 = 0;
        int ret = 0;
 
@@ -158,11 +158,11 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
                if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
                        filp->f_pos = old_pos;
-                       if (tempname != (char *)de->name) kfree(tempname);
+                       if (tempname != de->name) kfree(tempname);
                        hpfs_brelse4(&qbh);
                        goto out;
                }
-               if (tempname != (char *)de->name) kfree(tempname);
+               if (tempname != de->name) kfree(tempname);
                hpfs_brelse4(&qbh);
        }
 out:
@@ -187,7 +187,7 @@ out:
 
 struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
@@ -197,7 +197,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
        struct hpfs_inode_info *hpfs_result;
 
        lock_kernel();
-       if ((err = hpfs_chk_name((char *)name, &len))) {
+       if ((err = hpfs_chk_name(name, &len))) {
                if (err == -ENAMETOOLONG) {
                        unlock_kernel();
                        return ERR_PTR(-ENAMETOOLONG);
@@ -209,7 +209,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
         * '.' and '..' will never be passed here.
         */
 
-       de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *) name, len, NULL, &qbh);
+       de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, NULL, &qbh);
 
        /*
         * This is not really a bailout, just means file not found.
@@ -250,7 +250,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
        hpfs_result = hpfs_i(result);
        if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
 
-       hpfs_decide_conv(result, (char *)name, len);
+       hpfs_decide_conv(result, name, len);
 
        if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
                hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
index fe83c2b7d2d8bb8899ca47e0f90ce5741ff3bbc4..9b2ffadfc8c42dd9a39f86a0bdedb6a8dbbd0df5 100644 (file)
@@ -158,7 +158,8 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno
 
 /* Add an entry to dnode and don't care if it grows over 2048 bytes */
 
-struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, unsigned char *name,
+struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
+                               const unsigned char *name,
                                unsigned namelen, secno down_ptr)
 {
        struct hpfs_dirent *de;
@@ -223,7 +224,7 @@ static void fix_up_ptrs(struct super_block *s, struct dnode *d)
 /* Add an entry to dnode and do dnode splitting if required */
 
 static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
-                            unsigned char *name, unsigned namelen,
+                            const unsigned char *name, unsigned namelen,
                             struct hpfs_dirent *new_de, dnode_secno down_ptr)
 {
        struct quad_buffer_head qbh, qbh1, qbh2;
@@ -231,7 +232,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
        dnode_secno adno, rdno;
        struct hpfs_dirent *de;
        struct hpfs_dirent nde;
-       char *nname;
+       unsigned char *nname;
        int h;
        int pos;
        struct buffer_head *bh;
@@ -305,7 +306,9 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
                pos++;
        }
        copy_de(new_de = &nde, de);
-       memcpy(name = nname, de->name, namelen = de->namelen);
+       memcpy(nname, de->name, de->namelen);
+       name = nname;
+       namelen = de->namelen;
        for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, 4);
        down_ptr = adno;
        set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
@@ -368,7 +371,8 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
  * I hope, now it's finally bug-free.
  */
 
-int hpfs_add_dirent(struct inode *i, unsigned char *name, unsigned namelen,
+int hpfs_add_dirent(struct inode *i,
+                   const unsigned char *name, unsigned namelen,
                    struct hpfs_dirent *new_de, int cdepth)
 {
        struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
@@ -897,7 +901,8 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
 
 /* Find a dirent in tree */
 
-struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno, char *name, unsigned len,
+struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno,
+                              const unsigned char *name, unsigned len,
                               dnode_secno *dd, struct quad_buffer_head *qbh)
 {
        struct dnode *dnode;
@@ -988,8 +993,8 @@ void hpfs_remove_dtree(struct super_block *s, dnode_secno dno)
 struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
                                     struct fnode *f, struct quad_buffer_head *qbh)
 {
-       char *name1;
-       char *name2;
+       unsigned char *name1;
+       unsigned char *name2;
        int name1len, name2len;
        struct dnode *d;
        dnode_secno dno, downd;
index 547a8384571fcc9d1b95282933879125db098efa..45e53d972b42ed27e931c5fa01ae5fb194b0c5f2 100644 (file)
@@ -62,8 +62,8 @@ static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
        return ret;
 }
 
-static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
-                           int size)
+static void set_indirect_ea(struct super_block *s, int ano, secno a,
+                           const char *data, int size)
 {
        hpfs_ea_write(s, a, ano, 0, size, data);
 }
@@ -186,7 +186,8 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
  * This driver can't change sizes of eas ('cause I just don't need it).
  */
 
-void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data, int size)
+void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
+                const char *data, int size)
 {
        fnode_secno fno = inode->i_ino;
        struct super_block *s = inode->i_sb;
index 701ca54c0867fe482b9c33fdb6615a015114fa95..97bf738cd5d65117b4610a707738dd9accd8c2eb 100644 (file)
@@ -215,7 +215,7 @@ secno hpfs_bplus_lookup(struct super_block *, struct inode *, struct bplus_heade
 secno hpfs_add_sector_to_btree(struct super_block *, secno, int, unsigned);
 void hpfs_remove_btree(struct super_block *, struct bplus_header *);
 int hpfs_ea_read(struct super_block *, secno, int, unsigned, unsigned, char *);
-int hpfs_ea_write(struct super_block *, secno, int, unsigned, unsigned, char *);
+int hpfs_ea_write(struct super_block *, secno, int, unsigned, unsigned, const char *);
 void hpfs_ea_remove(struct super_block *, secno, int, unsigned);
 void hpfs_truncate_btree(struct super_block *, secno, int, unsigned);
 void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
@@ -244,13 +244,17 @@ extern const struct file_operations hpfs_dir_ops;
 
 void hpfs_add_pos(struct inode *, loff_t *);
 void hpfs_del_pos(struct inode *, loff_t *);
-struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, unsigned char *, unsigned, secno);
-int hpfs_add_dirent(struct inode *, unsigned char *, unsigned, struct hpfs_dirent *, int);
+struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
+                               const unsigned char *, unsigned, secno);
+int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned,
+                   struct hpfs_dirent *, int);
 int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
 void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
 dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
 struct hpfs_dirent *map_pos_dirent(struct inode *, loff_t *, struct quad_buffer_head *);
-struct hpfs_dirent *map_dirent(struct inode *, dnode_secno, char *, unsigned, dnode_secno *, struct quad_buffer_head *);
+struct hpfs_dirent *map_dirent(struct inode *, dnode_secno,
+                              const unsigned char *, unsigned, dnode_secno *,
+                              struct quad_buffer_head *);
 void hpfs_remove_dtree(struct super_block *, dnode_secno);
 struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct fnode *, struct quad_buffer_head *);
 
@@ -259,7 +263,8 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct f
 void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
 int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
 char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
-void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
+void hpfs_set_ea(struct inode *, struct fnode *, const char *,
+                const char *, int);
 
 /* file.c */
 
@@ -282,7 +287,7 @@ void hpfs_delete_inode(struct inode *);
 
 unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
 unsigned *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
-char *hpfs_load_code_page(struct super_block *, secno);
+unsigned char *hpfs_load_code_page(struct super_block *, secno);
 secno *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
 struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
 struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);
@@ -292,12 +297,13 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino);
 /* name.c */
 
 unsigned char hpfs_upcase(unsigned char *, unsigned char);
-int hpfs_chk_name(unsigned char *, unsigned *);
-char *hpfs_translate_name(struct super_block *, unsigned char *, unsigned, int, int);
-int hpfs_compare_names(struct super_block *, unsigned char *, unsigned, unsigned char *, unsigned, int);
-int hpfs_is_name_long(unsigned char *, unsigned);
-void hpfs_adjust_length(unsigned char *, unsigned *);
-void hpfs_decide_conv(struct inode *, unsigned char *, unsigned);
+int hpfs_chk_name(const unsigned char *, unsigned *);
+unsigned char *hpfs_translate_name(struct super_block *, unsigned char *, unsigned, int, int);
+int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,
+                      const unsigned char *, unsigned, int);
+int hpfs_is_name_long(const unsigned char *, unsigned);
+void hpfs_adjust_length(const unsigned char *, unsigned *);
+void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);
 
 /* namei.c */
 
index fe703ae46bc773f95a8502f12ccae915531d4271..ff90affb94e16ebdd2b2a76156dab515d4a0a050 100644 (file)
@@ -46,7 +46,7 @@ void hpfs_read_inode(struct inode *i)
        struct fnode *fnode;
        struct super_block *sb = i->i_sb;
        struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-       unsigned char *ea;
+       void *ea;
        int ea_size;
 
        if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) {
@@ -112,7 +112,7 @@ void hpfs_read_inode(struct inode *i)
                }
        }
        if (fnode->dirflag) {
-               unsigned n_dnodes, n_subdirs;
+               int n_dnodes, n_subdirs;
                i->i_mode |= S_IFDIR;
                i->i_op = &hpfs_dir_iops;
                i->i_fop = &hpfs_dir_ops;
index c4724589b2eba1854f9d5afc7a274c1a9beed066..840d033ecee832561f7f9ed91cec78527a62e38f 100644 (file)
@@ -35,7 +35,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
  * lowercasing table
  */
 
-char *hpfs_load_code_page(struct super_block *s, secno cps)
+unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
 {
        struct buffer_head *bh;
        secno cpds;
@@ -71,7 +71,7 @@ char *hpfs_load_code_page(struct super_block *s, secno cps)
                brelse(bh);
                return NULL;
        }
-       ptr = (char *)cpd + cpd->offs[cpi] + 6;
+       ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6;
        if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
                printk("HPFS: out of memory for code page table\n");
                brelse(bh);
@@ -217,7 +217,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
        if ((dnode = hpfs_map_4sectors(s, secno, qbh, DNODE_RD_AHEAD)))
                if (hpfs_sb(s)->sb_chk) {
                        unsigned p, pp = 0;
-                       unsigned char *d = (char *)dnode;
+                       unsigned char *d = (unsigned char *)dnode;
                        int b = 0;
                        if (dnode->magic != DNODE_MAGIC) {
                                hpfs_error(s, "bad magic on dnode %08x", secno);
index 1f4a964384eb36f5286e5d917f4e7d0838b74b17..f24736d7a439218aa238f75df3338c3e3e64744f 100644 (file)
@@ -8,16 +8,16 @@
 
 #include "hpfs_fn.h"
 
-static char *text_postfix[]={
+static const char *text_postfix[]={
 ".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
 ".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
 ".RC", ".TEX", ".TXT", ".Y", ""};
 
-static char *text_prefix[]={
+static const char *text_prefix[]={
 "AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
 "MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
 
-void hpfs_decide_conv(struct inode *inode, unsigned char *name, unsigned len)
+void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len)
 {
        struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
        int i;
@@ -71,7 +71,7 @@ static inline unsigned char locase(unsigned char *dir, unsigned char a)
        return dir[a];
 }
 
-int hpfs_chk_name(unsigned char *name, unsigned *len)
+int hpfs_chk_name(const unsigned char *name, unsigned *len)
 {
        int i;
        if (*len > 254) return -ENAMETOOLONG;
@@ -83,10 +83,10 @@ int hpfs_chk_name(unsigned char *name, unsigned *len)
        return 0;
 }
 
-char *hpfs_translate_name(struct super_block *s, unsigned char *from,
+unsigned char *hpfs_translate_name(struct super_block *s, unsigned char *from,
                          unsigned len, int lc, int lng)
 {
-       char *to;
+       unsigned char *to;
        int i;
        if (hpfs_sb(s)->sb_chk >= 2) if (hpfs_is_name_long(from, len) != lng) {
                printk("HPFS: Long name flag mismatch - name ");
@@ -103,8 +103,9 @@ char *hpfs_translate_name(struct super_block *s, unsigned char *from,
        return to;
 }
 
-int hpfs_compare_names(struct super_block *s, unsigned char *n1, unsigned l1,
-                      unsigned char *n2, unsigned l2, int last)
+int hpfs_compare_names(struct super_block *s,
+                      const unsigned char *n1, unsigned l1,
+                      const unsigned char *n2, unsigned l2, int last)
 {
        unsigned l = l1 < l2 ? l1 : l2;
        unsigned i;
@@ -120,7 +121,7 @@ int hpfs_compare_names(struct super_block *s, unsigned char *n1, unsigned l1,
        return 0;
 }
 
-int hpfs_is_name_long(unsigned char *name, unsigned len)
+int hpfs_is_name_long(const unsigned char *name, unsigned len)
 {
        int i,j;
        for (i = 0; i < len && name[i] != '.'; i++)
@@ -134,7 +135,7 @@ int hpfs_is_name_long(unsigned char *name, unsigned len)
 
 /* OS/2 clears dots and spaces at the end of file name, so we have to */
 
-void hpfs_adjust_length(unsigned char *name, unsigned *len)
+void hpfs_adjust_length(const unsigned char *name, unsigned *len)
 {
        if (!*len) return;
        if (*len == 1 && name[0] == '.') return;
index 82b9c4ba9ed08b07eda6832d6a5953581f515967..11c2b4080f65d335d373e599bc374c9122d543a0 100644 (file)
@@ -11,7 +11,7 @@
 
 static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh0;
        struct buffer_head *bh;
@@ -24,7 +24,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        int r;
        struct hpfs_dirent dee;
        int err;
-       if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+       if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        lock_kernel();
        err = -ENOSPC;
        fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
@@ -62,7 +62,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                result->i_mode &= ~0222;
 
        mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee, 0);
        if (r == 1)
                goto bail3;
        if (r == -1) {
@@ -121,7 +121,7 @@ bail:
 
 static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct inode *result = NULL;
        struct buffer_head *bh;
@@ -130,7 +130,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        int r;
        struct hpfs_dirent dee;
        int err;
-       if ((err = hpfs_chk_name((char *)name, &len)))
+       if ((err = hpfs_chk_name(name, &len)))
                return err==-ENOENT ? -EINVAL : err;
        lock_kernel();
        err = -ENOSPC;
@@ -155,7 +155,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        result->i_op = &hpfs_file_iops;
        result->i_fop = &hpfs_file_ops;
        result->i_nlink = 1;
-       hpfs_decide_conv(result, (char *)name, len);
+       hpfs_decide_conv(result, name, len);
        hpfs_i(result)->i_parent_dir = dir->i_ino;
        result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
        result->i_ctime.tv_nsec = 0;
@@ -170,7 +170,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
        hpfs_i(result)->mmu_private = 0;
 
        mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee, 0);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -211,7 +211,7 @@ bail:
 
 static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct buffer_head *bh;
        struct fnode *fnode;
@@ -220,7 +220,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        struct hpfs_dirent dee;
        struct inode *result = NULL;
        int err;
-       if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+       if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
        if (!new_valid_dev(rdev))
                return -EINVAL;
@@ -256,7 +256,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
        init_special_inode(result, mode, rdev);
 
        mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee, 0);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -289,7 +289,7 @@ bail:
 
 static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct buffer_head *bh;
        struct fnode *fnode;
@@ -298,7 +298,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        struct hpfs_dirent dee;
        struct inode *result;
        int err;
-       if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+       if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        lock_kernel();
        if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
                unlock_kernel();
@@ -335,7 +335,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        result->i_data.a_ops = &hpfs_symlink_aops;
 
        mutex_lock(&hpfs_i(dir)->i_mutex);
-       r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+       r = hpfs_add_dirent(dir, name, len, &dee, 0);
        if (r == 1)
                goto bail2;
        if (r == -1) {
@@ -345,7 +345,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
        fnode->up = dir->i_ino;
-       hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
+       hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
        mark_buffer_dirty(bh);
        brelse(bh);
 
@@ -369,7 +369,7 @@ bail:
 
 static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
@@ -381,12 +381,12 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        int err;
 
        lock_kernel();
-       hpfs_adjust_length((char *)name, &len);
+       hpfs_adjust_length(name, &len);
 again:
        mutex_lock(&hpfs_i(inode)->i_parent_mutex);
        mutex_lock(&hpfs_i(dir)->i_mutex);
        err = -ENOENT;
-       de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
+       de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
                goto out;
 
@@ -413,22 +413,25 @@ again:
 
                mutex_unlock(&hpfs_i(dir)->i_mutex);
                mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
-               d_drop(dentry);
-               spin_lock(&dentry->d_lock);
-               if (atomic_read(&dentry->d_count) > 1 ||
-                   generic_permission(inode, MAY_WRITE, NULL) ||
+               dentry_unhash(dentry);
+               if (!d_unhashed(dentry)) {
+                       dput(dentry);
+                       unlock_kernel();
+                       return -ENOSPC;
+               }
+               if (generic_permission(inode, MAY_WRITE, NULL) ||
                    !S_ISREG(inode->i_mode) ||
                    get_write_access(inode)) {
-                       spin_unlock(&dentry->d_lock);
                        d_rehash(dentry);
+                       dput(dentry);
                } else {
                        struct iattr newattrs;
-                       spin_unlock(&dentry->d_lock);
                        /*printk("HPFS: truncating file before delete.\n");*/
                        newattrs.ia_size = 0;
                        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
                        err = notify_change(dentry, &newattrs);
                        put_write_access(inode);
+                       dput(dentry);
                        if (!err)
                                goto again;
                }
@@ -451,7 +454,7 @@ out:
 
 static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
@@ -462,12 +465,12 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
        int err;
        int r;
 
-       hpfs_adjust_length((char *)name, &len);
+       hpfs_adjust_length(name, &len);
        lock_kernel();
        mutex_lock(&hpfs_i(inode)->i_parent_mutex);
        mutex_lock(&hpfs_i(dir)->i_mutex);
        err = -ENOENT;
-       de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
+       de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
                goto out;
 
@@ -546,10 +549,10 @@ const struct address_space_operations hpfs_symlink_aops = {
 static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                struct inode *new_dir, struct dentry *new_dentry)
 {
-       char *old_name = (char *)old_dentry->d_name.name;
-       int old_len = old_dentry->d_name.len;
-       char *new_name = (char *)new_dentry->d_name.name;
-       int new_len = new_dentry->d_name.len;
+       const unsigned char *old_name = old_dentry->d_name.name;
+       unsigned old_len = old_dentry->d_name.len;
+       const unsigned char *new_name = new_dentry->d_name.name;
+       unsigned new_len = new_dentry->d_name.len;
        struct inode *i = old_dentry->d_inode;
        struct inode *new_inode = new_dentry->d_inode;
        struct quad_buffer_head qbh, qbh1;
@@ -560,9 +563,9 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct buffer_head *bh;
        struct fnode *fnode;
        int err;
-       if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
+       if ((err = hpfs_chk_name(new_name, &new_len))) return err;
        err = 0;
-       hpfs_adjust_length((char *)old_name, &old_len);
+       hpfs_adjust_length(old_name, &old_len);
 
        lock_kernel();
        /* order doesn't matter, due to VFS exclusion */
@@ -579,7 +582,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                goto end1;
        }
 
-       if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {
+       if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
                hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
                err = -ENOENT;
                goto end1;
@@ -590,7 +593,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (new_inode) {
                int r;
                if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
-                       if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, (char *)new_name, new_len, NULL, &qbh1))) {
+                       if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
                                clear_nlink(new_inode);
                                copy_de(nde, &de);
                                memcpy(nde->name, new_name, new_len);
@@ -618,7 +621,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        }
        
        if (new_dir == old_dir)
-               if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {
+               if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
                        hpfs_unlock_creation(i->i_sb);
                        hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
                        err = -ENOENT;
@@ -648,7 +651,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                brelse(bh);
        }
        hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
-       hpfs_decide_conv(i, (char *)new_name, new_len);
+       hpfs_decide_conv(i, new_name, new_len);
 end1:
        if (old_dir != new_dir)
                mutex_unlock(&hpfs_i(new_dir)->i_mutex);
index 7239efc690d833cf9e4a507916a5819270c1f267..2e4dfa8593da4c047a1a9028f6d8f8ce2b8b78bd 100644 (file)
@@ -718,7 +718,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
        struct vfsmount *proc_mnt;
        int err = -ENOENT;
 
-       proc_mnt = do_kern_mount("proc", 0, "proc", NULL);
+       proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt);
        if (IS_ERR(proc_mnt))
                goto out;
 
index e96a1667d749d5efa59b659fea5d1f0057ffb973..8a03a5447bdf392a826b088f7329c68af32f3d2e 100644 (file)
@@ -70,6 +70,8 @@ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
 
 extern void __init mnt_init(void);
 
+extern spinlock_t vfsmount_lock;
+
 /*
  * fs_struct.c
  */
index 6e8d17e1dc4c95db609308d2ef59c8e314be79fe..9e50bcf55857eaebd8fc4106f21bae8ad69afbf1 100644 (file)
@@ -338,28 +338,14 @@ int simple_readpage(struct file *file, struct page *page)
        return 0;
 }
 
-int simple_prepare_write(struct file *file, struct page *page,
-                       unsigned from, unsigned to)
-{
-       if (!PageUptodate(page)) {
-               if (to - from != PAGE_CACHE_SIZE)
-                       zero_user_segments(page,
-                               0, from,
-                               to, PAGE_CACHE_SIZE);
-       }
-       return 0;
-}
-
 int simple_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
 {
        struct page *page;
        pgoff_t index;
-       unsigned from;
 
        index = pos >> PAGE_CACHE_SHIFT;
-       from = pos & (PAGE_CACHE_SIZE - 1);
 
        page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
@@ -367,43 +353,59 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
 
        *pagep = page;
 
-       return simple_prepare_write(file, page, from, from+len);
-}
-
-static int simple_commit_write(struct file *file, struct page *page,
-                              unsigned from, unsigned to)
-{
-       struct inode *inode = page->mapping->host;
-       loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+       if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) {
+               unsigned from = pos & (PAGE_CACHE_SIZE - 1);
 
-       if (!PageUptodate(page))
-               SetPageUptodate(page);
-       /*
-        * No need to use i_size_read() here, the i_size
-        * cannot change under us because we hold the i_mutex.
-        */
-       if (pos > inode->i_size)
-               i_size_write(inode, pos);
-       set_page_dirty(page);
+               zero_user_segments(page, 0, from, from + len, PAGE_CACHE_SIZE);
+       }
        return 0;
 }
 
+/**
+ * simple_write_end - .write_end helper for non-block-device FSes
+ * @available: See .write_end of address_space_operations
+ * @file:              "
+ * @mapping:           "
+ * @pos:               "
+ * @len:               "
+ * @copied:            "
+ * @page:              "
+ * @fsdata:            "
+ *
+ * simple_write_end does the minimum needed for updating a page after writing is
+ * done. It has the same API signature as the .write_end of
+ * address_space_operations vector. So it can just be set onto .write_end for
+ * FSes that don't need any other processing. i_mutex is assumed to be held.
+ * Block based filesystems should use generic_write_end().
+ * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
+ * is not called, so a filesystem that actually does store data in .write_inode
+ * should extend on what's done here with a call to mark_inode_dirty() in the
+ * case that i_size has changed.
+ */
 int simple_write_end(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *page, void *fsdata)
 {
-       unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+       struct inode *inode = page->mapping->host;
+       loff_t last_pos = pos + copied;
 
        /* zero the stale part of the page if we did a short copy */
        if (copied < len) {
-               void *kaddr = kmap_atomic(page, KM_USER0);
-               memset(kaddr + from + copied, 0, len - copied);
-               flush_dcache_page(page);
-               kunmap_atomic(kaddr, KM_USER0);
+               unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+               zero_user(page, from + copied, len - copied);
        }
 
-       simple_commit_write(file, page, from, from+copied);
+       if (!PageUptodate(page))
+               SetPageUptodate(page);
+       /*
+        * No need to use i_size_read() here, the i_size
+        * cannot change under us because we hold the i_mutex.
+        */
+       if (last_pos > inode->i_size)
+               i_size_write(inode, last_pos);
 
+       set_page_dirty(page);
        unlock_page(page);
        page_cache_release(page);
 
@@ -853,7 +855,6 @@ EXPORT_SYMBOL(simple_getattr);
 EXPORT_SYMBOL(simple_link);
 EXPORT_SYMBOL(simple_lookup);
 EXPORT_SYMBOL(simple_pin_fs);
-EXPORT_UNUSED_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_readpage);
 EXPORT_SYMBOL(simple_release_fs);
 EXPORT_SYMBOL(simple_rename);
index a8794f233bc9c38d45c47f69d03652f7f6f8d533..ae9ded026b7cb18a783af01bffac31dd87d6a26e 100644 (file)
@@ -1182,8 +1182,9 @@ int __break_lease(struct inode *inode, unsigned int mode)
        struct file_lock *fl;
        unsigned long break_time;
        int i_have_this_lease = 0;
+       int want_write = (mode & O_ACCMODE) != O_RDONLY;
 
-       new_fl = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK);
+       new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
 
        lock_kernel();
 
@@ -1197,7 +1198,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
                if (fl->fl_owner == current->files)
                        i_have_this_lease = 1;
 
-       if (mode & FMODE_WRITE) {
+       if (want_write) {
                /* If we want write access, we have to revoke any lease. */
                future = F_UNLCK | F_INPROGRESS;
        } else if (flock->fl_type & F_INPROGRESS) {
index a4855af776a8b6670b753aa3af71203519de94a7..0741c69b33199da8c870cc0a05db479de0204b0a 100644 (file)
@@ -689,33 +689,20 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
        set_root(nd);
 
        while(1) {
-               struct vfsmount *parent;
                struct dentry *old = nd->path.dentry;
 
                if (nd->path.dentry == nd->root.dentry &&
                    nd->path.mnt == nd->root.mnt) {
                        break;
                }
-               spin_lock(&dcache_lock);
                if (nd->path.dentry != nd->path.mnt->mnt_root) {
-                       nd->path.dentry = dget(nd->path.dentry->d_parent);
-                       spin_unlock(&dcache_lock);
+                       /* rare case of legitimate dget_parent()... */
+                       nd->path.dentry = dget_parent(nd->path.dentry);
                        dput(old);
                        break;
                }
-               spin_unlock(&dcache_lock);
-               spin_lock(&vfsmount_lock);
-               parent = nd->path.mnt->mnt_parent;
-               if (parent == nd->path.mnt) {
-                       spin_unlock(&vfsmount_lock);
+               if (!follow_up(&nd->path))
                        break;
-               }
-               mntget(parent);
-               nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);
-               spin_unlock(&vfsmount_lock);
-               dput(old);
-               mntput(nd->path.mnt);
-               nd->path.mnt = parent;
        }
        follow_mount(&nd->path);
 }
@@ -1347,7 +1334,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim->d_name.name, victim, dir);
+       audit_inode_child(victim, dir);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
@@ -1503,7 +1490,7 @@ int may_open(struct path *path, int acc_mode, int flag)
         * An append-only file must be opened in append mode for writing.
         */
        if (IS_APPEND(inode)) {
-               if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
+               if  ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
                        return -EPERM;
                if (flag & O_TRUNC)
                        return -EPERM;
@@ -1547,7 +1534,7 @@ static int handle_truncate(struct path *path)
  * what get passed to sys_open().
  */
 static int __open_namei_create(struct nameidata *nd, struct path *path,
-                               int flag, int mode)
+                               int open_flag, int mode)
 {
        int error;
        struct dentry *dir = nd->path.dentry;
@@ -1565,7 +1552,7 @@ out_unlock:
        if (error)
                return error;
        /* Don't check for write permission, don't truncate */
-       return may_open(&nd->path, 0, flag & ~O_TRUNC);
+       return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
 }
 
 /*
@@ -1736,7 +1723,7 @@ do_last:
                error = mnt_want_write(nd.path.mnt);
                if (error)
                        goto exit_mutex_unlock;
-               error = __open_namei_create(&nd, &path, flag, mode);
+               error = __open_namei_create(&nd, &path, open_flag, mode);
                if (error) {
                        mnt_drop_write(nd.path.mnt);
                        goto exit;
@@ -1798,7 +1785,7 @@ ok:
                if (error)
                        goto exit;
        }
-       error = may_open(&nd.path, acc_mode, flag);
+       error = may_open(&nd.path, acc_mode, open_flag);
        if (error) {
                if (will_truncate)
                        mnt_drop_write(nd.path.mnt);
@@ -2275,8 +2262,11 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
                error = -EBUSY;
        else {
                error = security_inode_unlink(dir, dentry);
-               if (!error)
+               if (!error) {
                        error = dir->i_op->unlink(dir, dentry);
+                       if (!error)
+                               dentry->d_inode->i_flags |= S_DEAD;
+               }
        }
        mutex_unlock(&dentry->d_inode->i_mutex);
 
@@ -2629,6 +2619,8 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
        else
                error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
        if (!error) {
+               if (target)
+                       target->i_flags |= S_DEAD;
                if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
                        d_move(old_dentry, new_dentry);
        }
@@ -2671,11 +2663,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
        else
                error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-       if (!error) {
-               const char *new_name = old_dentry->d_name.name;
-               fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
+       if (!error)
+               fsnotify_move(old_dir, new_dir, old_name, is_dir,
                              new_dentry->d_inode, old_dentry);
-       }
        fsnotify_oldname_free(old_name);
 
        return error;
index c768f733c8d6585a87551190bdf1b71a14cab9fe..8174c8ab5c70e71316403e2f879a51c77566e422 100644 (file)
@@ -573,7 +573,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
                        mnt->mnt_master = old;
                        CLEAR_MNT_SHARED(mnt);
                } else if (!(flag & CL_PRIVATE)) {
-                       if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old))
+                       if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
                                list_add(&mnt->mnt_share, &old->mnt_share);
                        if (IS_MNT_SLAVE(old))
                                list_add(&mnt->mnt_slave, &old->mnt_slave);
@@ -737,6 +737,21 @@ static void m_stop(struct seq_file *m, void *v)
        up_read(&namespace_sem);
 }
 
+int mnt_had_events(struct proc_mounts *p)
+{
+       struct mnt_namespace *ns = p->ns;
+       int res = 0;
+
+       spin_lock(&vfsmount_lock);
+       if (p->event != ns->event) {
+               p->event = ns->event;
+               res = 1;
+       }
+       spin_unlock(&vfsmount_lock);
+
+       return res;
+}
+
 struct proc_fs_info {
        int flag;
        const char *str;
@@ -1121,8 +1136,15 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 {
        struct path path;
        int retval;
+       int lookup_flags = 0;
 
-       retval = user_path(name, &path);
+       if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+               return -EINVAL;
+
+       if (!(flags & UMOUNT_NOFOLLOW))
+               lookup_flags |= LOOKUP_FOLLOW;
+
+       retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
        if (retval)
                goto out;
        retval = -EINVAL;
@@ -1246,6 +1268,21 @@ void drop_collected_mounts(struct vfsmount *mnt)
        release_mounts(&umount_list);
 }
 
+int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+                  struct vfsmount *root)
+{
+       struct vfsmount *mnt;
+       int res = f(root, arg);
+       if (res)
+               return res;
+       list_for_each_entry(mnt, &root->mnt_list, mnt_list) {
+               res = f(mnt, arg);
+               if (res)
+                       return res;
+       }
+       return 0;
+}
+
 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
 {
        struct vfsmount *p;
@@ -1538,7 +1575,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
                err = do_remount_sb(sb, flags, data, 0);
        if (!err) {
                spin_lock(&vfsmount_lock);
-               mnt_flags |= path->mnt->mnt_flags & MNT_PNODE_MASK;
+               mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK;
                path->mnt->mnt_flags = mnt_flags;
                spin_unlock(&vfsmount_lock);
        }
@@ -1671,7 +1708,7 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path,
 {
        int err;
 
-       mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD);
+       mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
 
        down_write(&namespace_sem);
        /* Something was mounted here while we slept */
@@ -2314,17 +2351,13 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-       struct vfsmount *root;
        LIST_HEAD(umount_list);
 
-       if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock))
+       if (!atomic_dec_and_test(&ns->count))
                return;
-       root = ns->root;
-       ns->root = NULL;
-       spin_unlock(&vfsmount_lock);
        down_write(&namespace_sem);
        spin_lock(&vfsmount_lock);
-       umount_tree(root, 0, &umount_list);
+       umount_tree(ns->root, 0, &umount_list);
        spin_unlock(&vfsmount_lock);
        up_write(&namespace_sem);
        release_mounts(&umount_list);
index f141bde7756af861f1853a04bb919a78e377fe81..7570573bdb30dc670538e53951a1cf1a8d1a8d06 100644 (file)
@@ -574,14 +574,14 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
        nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
+static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
 {
        struct nfs_open_context *ctx;
 
        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (ctx != NULL) {
-               ctx->path.dentry = dget(dentry);
-               ctx->path.mnt = mntget(mnt);
+               ctx->path = *path;
+               path_get(&ctx->path);
                ctx->cred = get_rpccred(cred);
                ctx->state = NULL;
                ctx->lockowner = current->files;
@@ -686,7 +686,7 @@ int nfs_open(struct inode *inode, struct file *filp)
        cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+       ctx = alloc_nfs_open_context(&filp->f_path, cred);
        put_rpccred(cred);
        if (ctx == NULL)
                return -ENOMEM;
index 375f0fae2c6a9a4b9536ad416fdc011661ffa28b..84d83be25a98b4d8456fdaeb321f086d313b0e3f 100644 (file)
@@ -724,8 +724,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
        p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
        if (p->o_arg.seqid == NULL)
                goto err_free;
-       p->path.mnt = mntget(path->mnt);
-       p->path.dentry = dget(path->dentry);
+       path_get(path);
+       p->path = *path;
        p->dir = parent;
        p->owner = sp;
        atomic_inc(&sp->so_count);
@@ -1944,8 +1944,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
        calldata->res.seqid = calldata->arg.seqid;
        calldata->res.server = server;
        calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
-       calldata->path.mnt = mntget(path->mnt);
-       calldata->path.dentry = dget(path->dentry);
+       path_get(path);
+       calldata->path = *path;
 
        msg.rpc_argp = &calldata->arg,
        msg.rpc_resp = &calldata->res,
index d3854d94b7cf367cad8a04b665f0c18271355368..bf9cbd242dddbe5f7cda1969fc3eeebbd6e023ad 100644 (file)
@@ -36,10 +36,9 @@ static struct file *do_open(char *name, int flags)
                return ERR_PTR(error);
 
        if (flags == O_RDWR)
-               error = may_open(&nd.path, MAY_READ|MAY_WRITE,
-                                          FMODE_READ|FMODE_WRITE);
+               error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
        else
-               error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE);
+               error = may_open(&nd.path, MAY_WRITE, flags);
 
        if (!error)
                return dentry_open(nd.path.dentry, nd.path.mnt, flags,
index a8587e90fd5a837bfce993d9cebaeb9f1697f825..bbf72d8f9fc0a36bf10ef7a2c509e9f3239ea06e 100644 (file)
@@ -2121,9 +2121,15 @@ out_acl:
                 * and this is the root of a cross-mounted filesystem.
                 */
                if (ignore_crossmnt == 0 &&
-                   exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) {
-                       err = vfs_getattr(exp->ex_path.mnt->mnt_parent,
-                               exp->ex_path.mnt->mnt_mountpoint, &stat);
+                   dentry == exp->ex_path.mnt->mnt_root) {
+                       struct path path = exp->ex_path;
+                       path_get(&path);
+                       while (follow_up(&path)) {
+                               if (path.dentry != path.mnt->mnt_root)
+                                       break;
+                       }
+                       err = vfs_getattr(path.mnt, path.dentry, &stat);
+                       path_put(&path);
                        if (err)
                                goto out_nfserr;
                }
index 8715d194561aa626bff1d18991a2ac667be00715..15dc2deaac5f4d2feb4e47376c87b92977fe26d6 100644 (file)
@@ -361,7 +361,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
                 * If we are changing the size of the file, then
                 * we need to break all leases.
                 */
-               host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
+               host_err = break_lease(inode, O_WRONLY | O_NONBLOCK);
                if (host_err == -EWOULDBLOCK)
                        host_err = -ETIMEDOUT;
                if (host_err) /* ENOMEM or EWOULDBLOCK */
@@ -734,7 +734,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
         * Check to see if there are any leases on this file.
         * This may block while leases are broken.
         */
-       host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? FMODE_WRITE : 0));
+       host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
        if (host_err == -EWOULDBLOCK)
                host_err = -ETIMEDOUT;
        if (host_err) /* NOMEM or WOULDBLOCK */
index 76d803e060a95d983b633552a7a75c2b1bf42368..0092840492eee910ee80518072c0f754044b40be 100644 (file)
@@ -224,7 +224,7 @@ fail:
  * len <= NILFS_NAME_LEN and de != NULL are guaranteed by caller.
  */
 static int
-nilfs_match(int len, const char * const name, struct nilfs_dir_entry *de)
+nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de)
 {
        if (len != de->name_len)
                return 0;
@@ -349,11 +349,11 @@ done:
  * Entry is guaranteed to be valid.
  */
 struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *dir, struct dentry *dentry,
+nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
                 struct page **res_page)
 {
-       const char *name = dentry->d_name.name;
-       int namelen = dentry->d_name.len;
+       const unsigned char *name = qstr->name;
+       int namelen = qstr->len;
        unsigned reclen = NILFS_DIR_REC_LEN(namelen);
        unsigned long start, n;
        unsigned long npages = dir_pages(dir);
@@ -424,13 +424,13 @@ struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
        return de;
 }
 
-ino_t nilfs_inode_by_name(struct inode *dir, struct dentry *dentry)
+ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
 {
        ino_t res = 0;
        struct nilfs_dir_entry *de;
        struct page *page;
 
-       de = nilfs_find_entry(dir, dentry, &page);
+       de = nilfs_find_entry(dir, qstr, &page);
        if (de) {
                res = le64_to_cpu(de->inode);
                kunmap(page);
@@ -465,7 +465,7 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
 int nilfs_add_link(struct dentry *dentry, struct inode *inode)
 {
        struct inode *dir = dentry->d_parent->d_inode;
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        unsigned chunk_size = nilfs_chunk_size(dir);
        unsigned reclen = NILFS_DIR_REC_LEN(namelen);
index 07ba838ef089231d5ba387d9220bb16402c193a2..ad6ed2cf19b4b5d31f3b7a80cfe11377b5acfceb 100644 (file)
@@ -67,7 +67,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        if (dentry->d_name.len > NILFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       ino = nilfs_inode_by_name(dir, dentry);
+       ino = nilfs_inode_by_name(dir, &dentry->d_name);
        inode = NULL;
        if (ino) {
                inode = nilfs_iget(dir->i_sb, ino);
@@ -81,10 +81,7 @@ struct dentry *nilfs_get_parent(struct dentry *child)
 {
        unsigned long ino;
        struct inode *inode;
-       struct dentry dotdot;
-
-       dotdot.d_name.name = "..";
-       dotdot.d_name.len = 2;
+       struct qstr dotdot = {.name = "..", .len = 2};
 
        ino = nilfs_inode_by_name(child->d_inode, &dotdot);
        if (!ino)
@@ -296,7 +293,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
        int err;
 
        err = -ENOENT;
-       de = nilfs_find_entry(dir, dentry, &page);
+       de = nilfs_find_entry(dir, &dentry->d_name, &page);
        if (!de)
                goto out;
 
@@ -389,7 +386,7 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                return err;
 
        err = -ENOENT;
-       old_de = nilfs_find_entry(old_dir, old_dentry, &old_page);
+       old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_page);
        if (!old_de)
                goto out;
 
@@ -409,7 +406,7 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        goto out_dir;
 
                err = -ENOENT;
-               new_de = nilfs_find_entry(new_dir, new_dentry, &new_page);
+               new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_page);
                if (!new_de)
                        goto out_dir;
                inc_nlink(old_inode);
index 4da6f67e9a915aeb2096cc03cb47ec09a40f0338..8723e5bfd0717921ccbcfa526ed874d5eea2b8ea 100644 (file)
@@ -217,10 +217,10 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
 
 /* dir.c */
 extern int nilfs_add_link(struct dentry *, struct inode *);
-extern ino_t nilfs_inode_by_name(struct inode *, struct dentry *);
+extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
 extern int nilfs_make_empty(struct inode *, struct inode *);
 extern struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *, struct dentry *, struct page **);
+nilfs_find_entry(struct inode *, const struct qstr *, struct page **);
 extern int nilfs_delete_entry(struct nilfs_dir_entry *, struct page *);
 extern int nilfs_empty_dir(struct inode *);
 extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
index a94e8bd8eb1f8274372940271970e0506ac3df50..472cdf29ef82598586a52f32c405bc43a8ab6b26 100644 (file)
 #include <linux/init.h> /* module_init */
 #include <linux/inotify.h>
 #include <linux/kernel.h> /* roundup() */
-#include <linux/magic.h> /* superblock magic number */
-#include <linux/mount.h> /* mntget */
 #include <linux/namei.h> /* LOOKUP_FOLLOW */
-#include <linux/path.h> /* struct path */
 #include <linux/sched.h> /* struct user */
 #include <linux/slab.h> /* struct kmem_cache */
 #include <linux/syscalls.h>
 #include <linux/types.h>
+#include <linux/anon_inodes.h>
 #include <linux/uaccess.h>
 #include <linux/poll.h>
 #include <linux/wait.h>
@@ -45,8 +43,6 @@
 
 #include <asm/ioctls.h>
 
-static struct vfsmount *inotify_mnt __read_mostly;
-
 /* these are configurable via /proc/sys/fs/inotify/ */
 static int inotify_max_user_instances __read_mostly;
 static int inotify_max_queued_events __read_mostly;
@@ -645,9 +641,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
 {
        struct fsnotify_group *group;
        struct user_struct *user;
-       struct file *filp;
-       struct path path;
-       int fd, ret;
+       int ret;
 
        /* Check the IN_* constants for consistency.  */
        BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC);
@@ -656,10 +650,6 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
                return -EINVAL;
 
-       fd = get_unused_fd_flags(flags & O_CLOEXEC);
-       if (fd < 0)
-               return fd;
-
        user = get_current_user();
        if (unlikely(atomic_read(&user->inotify_devs) >=
                        inotify_max_user_instances)) {
@@ -676,27 +666,14 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
 
        atomic_inc(&user->inotify_devs);
 
-       path.mnt = inotify_mnt;
-       path.dentry = inotify_mnt->mnt_root;
-       path_get(&path);
-       filp = alloc_file(&path, FMODE_READ, &inotify_fops);
-       if (!filp)
-               goto Enfile;
+       ret = anon_inode_getfd("inotify", &inotify_fops, group,
+                                 O_RDONLY | flags);
+       if (ret >= 0)
+               return ret;
 
-       filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
-       filp->private_data = group;
-
-       fd_install(fd, filp);
-
-       return fd;
-
-Enfile:
-       ret = -ENFILE;
-       path_put(&path);
        atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
-       put_unused_fd(fd);
        return ret;
 }
 
@@ -783,20 +760,6 @@ out:
        return ret;
 }
 
-static int
-inotify_get_sb(struct file_system_type *fs_type, int flags,
-              const char *dev_name, void *data, struct vfsmount *mnt)
-{
-       return get_sb_pseudo(fs_type, "inotify", NULL,
-                       INOTIFYFS_SUPER_MAGIC, mnt);
-}
-
-static struct file_system_type inotify_fs_type = {
-    .name      = "inotifyfs",
-    .get_sb    = inotify_get_sb,
-    .kill_sb   = kill_anon_super,
-};
-
 /*
  * inotify_user_setup - Our initialization function.  Note that we cannnot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
@@ -804,16 +767,6 @@ static struct file_system_type inotify_fs_type = {
  */
 static int __init inotify_user_setup(void)
 {
-       int ret;
-
-       ret = register_filesystem(&inotify_fs_type);
-       if (unlikely(ret))
-               panic("inotify: register_filesystem returned %d!\n", ret);
-
-       inotify_mnt = kern_mount(&inotify_fs_type);
-       if (IS_ERR(inotify_mnt))
-               panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
-
        inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark_entry, SLAB_PANIC);
        event_priv_cachep = KMEM_CACHE(inotify_event_private_data, SLAB_PANIC);
 
index 040cef72bc00e46a0c58790f1c18cef7722756c8..e0b2d88b03800863f367b67096aa093a3f70ea11 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -271,7 +271,7 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
         * Make sure that there are no leases.  get_write_access() protects
         * against the truncate racing with a lease-granting setlease().
         */
-       error = break_lease(inode, FMODE_WRITE);
+       error = break_lease(inode, O_WRONLY);
        if (error)
                goto put_write_and_out;
 
index 8d5f392ec3d39fa12a025ec3a6045b7ef8f790a4..5cc564a83149a5fc311b57d87793febbdcfd4f27 100644 (file)
@@ -86,7 +86,7 @@ static int do_make_slave(struct vfsmount *mnt)
 
        /*
         * slave 'mnt' to a peer mount that has the
-        * same root dentry. If none is available than
+        * same root dentry. If none is available then
         * slave it to anything that is available.
         */
        while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
@@ -147,6 +147,11 @@ void change_mnt_propagation(struct vfsmount *mnt, int type)
  * get the next mount in the propagation tree.
  * @m: the mount seen last
  * @origin: the original mount from where the tree walk initiated
+ *
+ * Note that peer groups form contiguous segments of slave lists.
+ * We rely on that in get_source() to be able to find out if
+ * vfsmount found while iterating with propagation_next() is
+ * a peer of one we'd found earlier.
  */
 static struct vfsmount *propagation_next(struct vfsmount *m,
                                         struct vfsmount *origin)
@@ -186,10 +191,6 @@ static struct vfsmount *get_source(struct vfsmount *dest,
 {
        struct vfsmount *p_last_src = NULL;
        struct vfsmount *p_last_dest = NULL;
-       *type = CL_PROPAGATION;
-
-       if (IS_MNT_SHARED(dest))
-               *type |= CL_MAKE_SHARED;
 
        while (last_dest != dest->mnt_master) {
                p_last_dest = last_dest;
@@ -202,13 +203,18 @@ static struct vfsmount *get_source(struct vfsmount *dest,
                do {
                        p_last_dest = next_peer(p_last_dest);
                } while (IS_MNT_NEW(p_last_dest));
+               /* is that a peer of the earlier? */
+               if (dest == p_last_dest) {
+                       *type = CL_MAKE_SHARED;
+                       return p_last_src;
+               }
        }
-
-       if (dest != p_last_dest) {
-               *type |= CL_SLAVE;
-               return last_src;
-       } else
-               return p_last_src;
+       /* slave of the earlier, then */
+       *type = CL_SLAVE;
+       /* beginning of peer group among the slaves? */
+       if (IS_MNT_SHARED(dest))
+               *type |= CL_MAKE_SHARED;
+       return last_src;
 }
 
 /*
index 958665d662af24f4e7bea120a959c6220a91b1f5..1ea4ae1efcd3f898097a011360bb978c29f7b565 100644 (file)
 #define CL_SLAVE               0x02
 #define CL_COPY_ALL            0x04
 #define CL_MAKE_SHARED                 0x08
-#define CL_PROPAGATION                 0x10
-#define CL_PRIVATE             0x20
+#define CL_PRIVATE             0x10
 
 static inline void set_mnt_shared(struct vfsmount *mnt)
 {
-       mnt->mnt_flags &= ~MNT_PNODE_MASK;
+       mnt->mnt_flags &= ~MNT_SHARED_MASK;
        mnt->mnt_flags |= MNT_SHARED;
 }
 
index 623e2ffb5d2bb5ae7fbb153af881a24f6f9932a0..a7310841c83149e406c1089d30a8c27b2c1e67fb 100644 (file)
@@ -647,17 +647,11 @@ static int mounts_release(struct inode *inode, struct file *file)
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
        struct proc_mounts *p = file->private_data;
-       struct mnt_namespace *ns = p->ns;
        unsigned res = POLLIN | POLLRDNORM;
 
-       poll_wait(file, &ns->poll, wait);
-
-       spin_lock(&vfsmount_lock);
-       if (p->event != ns->event) {
-               p->event = ns->event;
+       poll_wait(file, &p->ns->poll, wait);
+       if (mnt_had_events(p))
                res |= POLLERR | POLLPRI;
-       }
-       spin_unlock(&vfsmount_lock);
 
        return res;
 }
index 480cb1065eec8a65d9224075ffc66858dd4d738f..9580abeadeb37903d93f78262927f8f2e116b385 100644 (file)
@@ -662,6 +662,7 @@ struct proc_dir_entry *proc_symlink(const char *name,
        }
        return ent;
 }
+EXPORT_SYMBOL(proc_symlink);
 
 struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
                struct proc_dir_entry *parent)
@@ -700,6 +701,7 @@ struct proc_dir_entry *proc_mkdir(const char *name,
 {
        return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
 }
+EXPORT_SYMBOL(proc_mkdir);
 
 struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                                         struct proc_dir_entry *parent)
@@ -728,6 +730,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
        }
        return ent;
 }
+EXPORT_SYMBOL(create_proc_entry);
 
 struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
                                        struct proc_dir_entry *parent,
@@ -762,6 +765,7 @@ out_free:
 out:
        return NULL;
 }
+EXPORT_SYMBOL(proc_create_data);
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
@@ -853,3 +857,4 @@ continue_removing:
                        de->parent->name, de->name, de->subdir->name);
        pde_put(de);
 }
+EXPORT_SYMBOL(remove_proc_entry);
index b080b791d9e313b580882a0163de92fbb22886b9..757c069f2a65132584272d3fc1ccd22ea012d737 100644 (file)
@@ -220,9 +220,3 @@ void pid_ns_release_proc(struct pid_namespace *ns)
 {
        mntput(ns->proc_mnt);
 }
-
-EXPORT_SYMBOL(proc_symlink);
-EXPORT_SYMBOL(proc_mkdir);
-EXPORT_SYMBOL(create_proc_entry);
-EXPORT_SYMBOL(proc_create_data);
-EXPORT_SYMBOL(remove_proc_entry);
index aff046b0fe78b8be88b7a81a10f2ed39b38e2f85..f35ac6022109d3a61e1ddb7cabbc67db8d5cf107 100644 (file)
@@ -568,7 +568,7 @@ out:
 int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 {
        int retval;
-       int remount_rw;
+       int remount_rw, remount_ro;
 
        if (sb->s_frozen != SB_UNFROZEN)
                return -EBUSY;
@@ -583,9 +583,12 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
        shrink_dcache_sb(sb);
        sync_filesystem(sb);
 
+       remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY);
+       remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
+
        /* If we are remounting RDONLY and current sb is read/write,
           make sure there are no rw files opened */
-       if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
+       if (remount_ro) {
                if (force)
                        mark_files_ro(sb);
                else if (!fs_may_remount_ro(sb))
@@ -594,7 +597,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
                if (retval < 0 && retval != -ENOSYS)
                        return -EBUSY;
        }
-       remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
 
        if (sb->s_op->remount_fs) {
                retval = sb->s_op->remount_fs(sb, &flags, data);
@@ -604,6 +606,16 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
        sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
        if (remount_rw)
                vfs_dq_quota_on_remount(sb);
+       /*
+        * Some filesystems modify their metadata via some other path than the
+        * bdev buffer cache (eg. use a private mapping, or directories in
+        * pagecache, etc). Also file data modifications go via their own
+        * mappings. So If we try to mount readonly then copy the filesystem
+        * from bdev, we could get stale data, so invalidate it to give a best
+        * effort at coherency.
+        */
+       if (remount_ro && sb->s_bdev)
+               invalidate_bdev(sb->s_bdev);
        return 0;
 }
 
@@ -925,6 +937,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        if (!mnt)
                goto out;
 
+       if (flags & MS_KERNMOUNT)
+               mnt->mnt_flags = MNT_INTERNAL;
+
        if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
                secdata = alloc_secdata();
                if (!secdata)
index 82372e332f08521010183f0ce6c2a674f7912b7f..b2d96f45c12b97becf57e58b9034b84b1092dd94 100644 (file)
@@ -547,7 +547,7 @@ static void udf_table_free_blocks(struct super_block *sb,
                }
 
                if (epos.offset + (2 * adsize) > sb->s_blocksize) {
-                       char *sptr, *dptr;
+                       unsigned char *sptr, *dptr;
                        int loffset;
 
                        brelse(oepos.bh);
index 61d9a76a3a69dd109e3b3051e9bc89ddaa92990d..f0f2a436251e4cfcbc40ba9e7e3c6ee69dde47e0 100644 (file)
@@ -45,8 +45,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
        int block, iblock;
        loff_t nf_pos = (filp->f_pos - 1) << 2;
        int flen;
-       char *fname = NULL;
-       char *nameptr;
+       unsigned char *fname = NULL;
+       unsigned char *nameptr;
        uint16_t liu;
        uint8_t lfi;
        loff_t size = udf_ext0_offset(dir) + dir->i_size;
index f90231eb29165785d14369191a00fc458dafbc9c..378a7592257c85f96c5423d07671e3c725819311 100644 (file)
@@ -1672,7 +1672,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
                return -1;
 
        if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
-               char *sptr, *dptr;
+               unsigned char *sptr, *dptr;
                struct buffer_head *nbh;
                int err, loffset;
                struct kernel_lb_addr obloc = epos->block;
index cd2115060fdcc728aeefc7a21e80f6fc6af9c28c..7c56ff00cd534e6c9fce548c771b5d3e526d34d2 100644 (file)
@@ -34,8 +34,8 @@
 #include <linux/crc-itu-t.h>
 #include <linux/exportfs.h>
 
-static inline int udf_match(int len1, const char *name1, int len2,
-                           const char *name2)
+static inline int udf_match(int len1, const unsigned char *name1, int len2,
+                           const unsigned char *name2)
 {
        if (len1 != len2)
                return 0;
@@ -142,15 +142,15 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
 }
 
 static struct fileIdentDesc *udf_find_entry(struct inode *dir,
-                                           struct qstr *child,
+                                           const struct qstr *child,
                                            struct udf_fileident_bh *fibh,
                                            struct fileIdentDesc *cfi)
 {
        struct fileIdentDesc *fi = NULL;
        loff_t f_pos;
        int block, flen;
-       char *fname = NULL;
-       char *nameptr;
+       unsigned char *fname = NULL;
+       unsigned char *nameptr;
        uint8_t lfi;
        uint16_t liu;
        loff_t size;
@@ -308,7 +308,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 {
        struct super_block *sb = dir->i_sb;
        struct fileIdentDesc *fi = NULL;
-       char *name = NULL;
+       unsigned char *name = NULL;
        int namelen;
        loff_t f_pos;
        loff_t size = udf_ext0_offset(dir) + dir->i_size;
@@ -885,16 +885,16 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
 {
        struct inode *inode;
        struct pathComponent *pc;
-       char *compstart;
+       const char *compstart;
        struct udf_fileident_bh fibh;
        struct extent_position epos = {};
        int eoffset, elen = 0;
        struct fileIdentDesc *fi;
        struct fileIdentDesc cfi;
-       char *ea;
+       uint8_t *ea;
        int err;
        int block;
-       char *name = NULL;
+       unsigned char *name = NULL;
        int namelen;
        struct buffer_head *bh;
        struct udf_inode_info *iinfo;
@@ -970,7 +970,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
 
                pc = (struct pathComponent *)(ea + elen);
 
-               compstart = (char *)symname;
+               compstart = symname;
 
                do {
                        symname++;
index c3265e1385d43c5c6ed0e2960cf9d83a72493e4a..852e91845688f24be5b1fa464b70a4d65a044b2a 100644 (file)
 #include <linux/buffer_head.h>
 #include "udf_i.h"
 
-static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen,
-                          char *to)
+static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
+                          int fromlen, unsigned char *to)
 {
        struct pathComponent *pc;
        int elen = 0;
-       char *p = to;
+       unsigned char *p = to;
 
        while (elen < fromlen) {
                pc = (struct pathComponent *)(from + elen);
@@ -75,9 +75,9 @@ static int udf_symlink_filler(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
        struct buffer_head *bh = NULL;
-       char *symlink;
+       unsigned char *symlink;
        int err = -EIO;
-       char *p = kmap(page);
+       unsigned char *p = kmap(page);
        struct udf_inode_info *iinfo;
 
        lock_kernel();
index 22af68f8b6825e4be3343ecb79ed4dbec587f61b..317a0d444f6b32e82f79a80c90900e67a3da7f08 100644 (file)
@@ -31,7 +31,7 @@
  * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
  */
 static inline int ufs_match(struct super_block *sb, int len,
-               const char * const name, struct ufs_dir_entry * de)
+               const unsigned char *name, struct ufs_dir_entry *de)
 {
        if (len != ufs_get_de_namlen(sb, de))
                return 0;
@@ -70,7 +70,7 @@ static inline unsigned long ufs_dir_pages(struct inode *inode)
        return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
 }
 
-ino_t ufs_inode_by_name(struct inode *dir, struct qstr *qstr)
+ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr)
 {
        ino_t res = 0;
        struct ufs_dir_entry *de;
@@ -249,11 +249,11 @@ struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p)
  * (as a parameter - res_dir). Page is returned mapped and unlocked.
  * Entry is guaranteed to be valid.
  */
-struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct qstr *qstr,
+struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr,
                                     struct page **res_page)
 {
        struct super_block *sb = dir->i_sb;
-       const char *name = qstr->name;
+       const unsigned char *name = qstr->name;
        int namelen = qstr->len;
        unsigned reclen = UFS_DIR_REC_LEN(namelen);
        unsigned long start, n;
@@ -313,7 +313,7 @@ found:
 int ufs_add_link(struct dentry *dentry, struct inode *inode)
 {
        struct inode *dir = dentry->d_parent->d_inode;
-       const char *name = dentry->d_name.name;
+       const unsigned char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        struct super_block *sb = dir->i_sb;
        unsigned reclen = UFS_DIR_REC_LEN(namelen);
index 0b4c39bc0d9ef716b3a81b9ee44dc09f87f48e57..01d0e2a3b230f596b567ac1c5a3e4bb432a5abfa 100644 (file)
@@ -86,9 +86,9 @@ extern void ufs_put_cylinder (struct super_block *, unsigned);
 /* dir.c */
 extern const struct inode_operations ufs_dir_inode_operations;
 extern int ufs_add_link (struct dentry *, struct inode *);
-extern ino_t ufs_inode_by_name(struct inode *, struct qstr *);
+extern ino_t ufs_inode_by_name(struct inode *, const struct qstr *);
 extern int ufs_make_empty(struct inode *, struct inode *);
-extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct qstr *, struct page **);
+extern struct ufs_dir_entry *ufs_find_entry(struct inode *, const struct qstr *, struct page **);
 extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
 extern int ufs_empty_dir (struct inode *);
 extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
index 3c7a358241a71d78c9aa288f08b1d83a61a1abb8..f391d45c8aea42eea13a21fcc3356313de63bd33 100644 (file)
@@ -424,7 +424,7 @@ extern void audit_syscall_exit(int failed, long return_code);
 extern void __audit_getname(const char *name);
 extern void audit_putname(const char *name);
 extern void __audit_inode(const char *name, const struct dentry *dentry);
-extern void __audit_inode_child(const char *dname, const struct dentry *dentry,
+extern void __audit_inode_child(const struct dentry *dentry,
                                const struct inode *parent);
 extern void __audit_ptrace(struct task_struct *t);
 
@@ -442,11 +442,10 @@ static inline void audit_inode(const char *name, const struct dentry *dentry) {
        if (unlikely(!audit_dummy_context()))
                __audit_inode(name, dentry);
 }
-static inline void audit_inode_child(const char *dname, 
-                                    const struct dentry *dentry,
+static inline void audit_inode_child(const struct dentry *dentry,
                                     const struct inode *parent) {
        if (unlikely(!audit_dummy_context()))
-               __audit_inode_child(dname, dentry, parent);
+               __audit_inode_child(dentry, parent);
 }
 void audit_core_dumps(long signr);
 
@@ -544,9 +543,9 @@ extern int audit_signals;
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
 #define __audit_inode(n,d) do { ; } while (0)
-#define __audit_inode_child(d,i,p) do { ; } while (0)
+#define __audit_inode_child(i,p) do { ; } while (0)
 #define audit_inode(n,d) do { ; } while (0)
-#define audit_inode_child(d,i,p) do { ; } while (0)
+#define audit_inode_child(i,p) do { ; } while (0)
 #define audit_core_dumps(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) (0)
 #define audit_get_loginuid(t) (-1)
index ebb1cd5bc2419c7fad8b421178021d52ac005fea..5b3182c7eb5fccbcdec153782eceec174dc87808 100644 (file)
@@ -1305,6 +1305,8 @@ extern int send_sigurg(struct fown_struct *fown);
 #define MNT_FORCE      0x00000001      /* Attempt to forcibily umount */
 #define MNT_DETACH     0x00000002      /* Just detach from the tree */
 #define MNT_EXPIRE     0x00000004      /* Mark for expiry */
+#define UMOUNT_NOFOLLOW        0x00000008      /* Don't follow symlink on umount */
+#define UMOUNT_UNUSED  0x80000000      /* Flag guaranteed to be unused */
 
 extern struct list_head super_blocks;
 extern spinlock_t sb_lock;
@@ -1314,9 +1316,9 @@ extern spinlock_t sb_lock;
 struct super_block {
        struct list_head        s_list;         /* Keep this first */
        dev_t                   s_dev;          /* search index; _not_ kdev_t */
-       unsigned long           s_blocksize;
-       unsigned char           s_blocksize_bits;
        unsigned char           s_dirt;
+       unsigned char           s_blocksize_bits;
+       unsigned long           s_blocksize;
        loff_t                  s_maxbytes;     /* Max file size */
        struct file_system_type *s_type;
        const struct super_operations   *s_op;
@@ -1357,16 +1359,16 @@ struct super_block {
        void                    *s_fs_info;     /* Filesystem private info */
        fmode_t                 s_mode;
 
+       /* Granularity of c/m/atime in ns.
+          Cannot be worse than a second */
+       u32                s_time_gran;
+
        /*
         * The next field is for VFS *only*. No filesystems have any business
         * even looking at it. You had been warned.
         */
        struct mutex s_vfs_rename_mutex;        /* Kludge */
 
-       /* Granularity of c/m/atime in ns.
-          Cannot be worse than a second */
-       u32                s_time_gran;
-
        /*
         * Filesystem subtype.  If non-empty the filesystem type field
         * in /proc/mounts will be "type.subtype"
@@ -1794,7 +1796,8 @@ extern int may_umount(struct vfsmount *);
 extern long do_mount(char *, char *, char *, unsigned long, void *);
 extern struct vfsmount *collect_mounts(struct path *);
 extern void drop_collected_mounts(struct vfsmount *);
-
+extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
+                         struct vfsmount *);
 extern int vfs_statfs(struct dentry *, struct kstatfs *);
 
 extern int current_umask(void);
@@ -2058,12 +2061,6 @@ extern int invalidate_inodes(struct super_block *);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
                                        pgoff_t start, pgoff_t end);
 
-static inline unsigned long __deprecated
-invalidate_inode_pages(struct address_space *mapping)
-{
-       return invalidate_mapping_pages(mapping, 0, ~0UL);
-}
-
 static inline void invalidate_remote_inode(struct inode *inode)
 {
        if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -2132,6 +2129,7 @@ extern struct file * open_exec(const char *);
  
 /* fs/dcache.c -- generic fs support functions */
 extern int is_subdir(struct dentry *, struct dentry *);
+extern int path_is_under(struct path *, struct path *);
 extern ino_t find_inode_number(struct dentry *, struct qstr *);
 
 #include <linux/err.h>
@@ -2340,8 +2338,6 @@ extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct
 extern int simple_sync_file(struct file *, struct dentry *, int);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
-extern int simple_prepare_write(struct file *file, struct page *page,
-                       unsigned offset, unsigned to);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata);
index 936f9aa8bb97581e5ff798e1d92035556eaf88cd..df8fd9a3b214b5afde8a1368b327358117e6fbdb 100644 (file)
@@ -65,7 +65,7 @@ static inline void fsnotify_link_count(struct inode *inode)
  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
  */
 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
-                                const char *old_name, const char *new_name,
+                                const char *old_name,
                                 int isdir, struct inode *target, struct dentry *moved)
 {
        struct inode *source = moved->d_inode;
@@ -73,6 +73,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
        u32 fs_cookie = fsnotify_get_cookie();
        __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
        __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
+       const char *new_name = moved->d_name.name;
 
        if (old_dir == new_dir)
                old_dir_mask |= FS_DN_RENAME;
@@ -103,7 +104,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
                inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
                fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
        }
-       audit_inode_child(new_name, moved, new_dir);
+       audit_inode_child(moved, new_dir);
 }
 
 /*
@@ -146,7 +147,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
        inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
                                  dentry->d_inode);
-       audit_inode_child(dentry->d_name.name, dentry, inode);
+       audit_inode_child(dentry, inode);
 
        fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
@@ -161,7 +162,7 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
        inotify_inode_queue_event(dir, IN_CREATE, 0, new_dentry->d_name.name,
                                  inode);
        fsnotify_link_count(inode);
-       audit_inode_child(new_dentry->d_name.name, new_dentry, dir);
+       audit_inode_child(new_dentry, dir);
 
        fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 }
@@ -175,7 +176,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
        struct inode *d_inode = dentry->d_inode;
 
        inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode);
-       audit_inode_child(dentry->d_name.name, dentry, inode);
+       audit_inode_child(dentry, inode);
 
        fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
index 76285e01b39ee1641336989ea99d727272645d0b..eb9800f05782413f640a0b3fcf68dbf1aa5ca7fa 100644 (file)
@@ -52,7 +52,6 @@
 #define CGROUP_SUPER_MAGIC     0x27e0eb
 
 #define FUTEXFS_SUPER_MAGIC    0xBAD1DEA
-#define INOTIFYFS_SUPER_MAGIC  0x2BAD1DEA
 
 #define STACK_END_MAGIC                0x57AC6E9D
 
index d74785c2393ad03976925e8ea6b63e3716718b79..0b89efc6f2155c1844775688c261d9ce52dc7957 100644 (file)
@@ -35,6 +35,7 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
 extern const struct seq_operations mounts_op;
 extern const struct seq_operations mountinfo_op;
 extern const struct seq_operations mountstats_op;
+extern int mnt_had_events(struct proc_mounts *);
 
 #endif
 #endif
index b5f43a34ef8841b9a2a5afe7fd961b85ad988d8b..4bd05474d11d557cd709ab3aa045902a8014af7c 100644 (file)
@@ -34,7 +34,18 @@ struct mnt_namespace;
 
 #define MNT_SHARED     0x1000  /* if the vfsmount is a shared mount */
 #define MNT_UNBINDABLE 0x2000  /* if the vfsmount is a unbindable mount */
-#define MNT_PNODE_MASK 0x3000  /* propagation flag mask */
+/*
+ * MNT_SHARED_MASK is the set of flags that should be cleared when a
+ * mount becomes shared.  Currently, this is only the flag that says a
+ * mount cannot be bind mounted, since this is how we create a mount
+ * that shares events with another mount.  If you add a new MNT_*
+ * flag, consider how it interacts with shared mounts.
+ */
+#define MNT_SHARED_MASK        (MNT_UNBINDABLE)
+#define MNT_PROPAGATION_MASK   (MNT_SHARED | MNT_UNBINDABLE)
+
+
+#define MNT_INTERNAL   0x4000
 
 struct vfsmount {
        struct list_head mnt_hash;
@@ -123,7 +134,6 @@ extern int do_add_mount(struct vfsmount *newmnt, struct path *path,
 
 extern void mark_mounts_for_expiry(struct list_head *mounts);
 
-extern spinlock_t vfsmount_lock;
 extern dev_t name_to_dev_t(char *name);
 
 #endif /* _LINUX_MOUNT_H */
index 614241b5200cf906c066288ac15a42df835490ce..2b108538d0d95684be2048fcc80a7acf484970c4 100644 (file)
@@ -30,11 +30,7 @@ static int __init do_linuxrc(void * shell)
        extern char * envp_init[];
 
        sys_close(old_fd);sys_close(root_fd);
-       sys_close(0);sys_close(1);sys_close(2);
        sys_setsid();
-       (void) sys_open("/dev/console",O_RDWR,0);
-       (void) sys_dup(0);
-       (void) sys_dup(0);
        return kernel_execve(shell, argv, envp_init);
 }
 
index 18098153c33170c782309f6275cb7f936cdcf6b0..40aaa020cd6818b04986aacfe180bc5cac054353 100644 (file)
@@ -822,11 +822,6 @@ static noinline int init_post(void)
        system_state = SYSTEM_RUNNING;
        numa_default_policy();
 
-       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
-
-       (void) sys_dup(0);
-       (void) sys_dup(0);
 
        current->signal->flags |= SIGNAL_UNKILLABLE;
 
@@ -889,6 +884,12 @@ static int __init kernel_init(void * unused)
 
        do_basic_setup();
 
+       /* Open the /dev/console on the rootfs, this should never fail */
+       if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+               printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+       (void) sys_dup(0);
+       (void) sys_dup(0);
        /*
         * check if there is an early userspace init.  If yes, let it do all
         * the work
index c79bd57353e73e0e68af8ca8fe1c41da787c7a61..b6cb06451f4be9295608a4156d3c32809773919a 100644 (file)
@@ -134,7 +134,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
                        init_waitqueue_head(&info->wait_q);
                        INIT_LIST_HEAD(&info->e_wait_q[0].list);
                        INIT_LIST_HEAD(&info->e_wait_q[1].list);
-                       info->messages = NULL;
                        info->notify_owner = NULL;
                        info->qsize = 0;
                        info->user = NULL;      /* set when all is ok */
@@ -146,6 +145,10 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
                                info->attr.mq_msgsize = attr->mq_msgsize;
                        }
                        mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+                       info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+                       if (!info->messages)
+                               goto out_inode;
+
                        mq_bytes = (mq_msg_tblsz +
                                (info->attr.mq_maxmsg * info->attr.mq_msgsize));
 
@@ -154,18 +157,12 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
                            u->mq_bytes + mq_bytes >
                            p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) {
                                spin_unlock(&mq_lock);
+                               kfree(info->messages);
                                goto out_inode;
                        }
                        u->mq_bytes += mq_bytes;
                        spin_unlock(&mq_lock);
 
-                       info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
-                       if (!info->messages) {
-                               spin_lock(&mq_lock);
-                               u->mq_bytes -= mq_bytes;
-                               spin_unlock(&mq_lock);
-                               goto out_inode;
-                       }
                        /* all is ok */
                        info->user = get_uid(u);
                } else if (S_ISDIR(mode)) {
@@ -187,7 +184,7 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *inode;
        struct ipc_namespace *ns = data;
-       int error = 0;
+       int error;
 
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -205,7 +202,9 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
        if (!sb->s_root) {
                iput(inode);
                error = -ENOMEM;
+               goto out;
        }
+       error = 0;
 
 out:
        return error;
@@ -264,8 +263,9 @@ static void mqueue_delete_inode(struct inode *inode)
 
        clear_inode(inode);
 
-       mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) +
-                  (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+       /* Total amount of bytes accounted for the mqueue */
+       mq_bytes = info->attr.mq_maxmsg * (sizeof(struct msg_msg *)
+           + info->attr.mq_msgsize);
        user = info->user;
        if (user) {
                spin_lock(&mq_lock);
@@ -604,8 +604,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
        /* check for overflow */
        if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
                return 0;
-       if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) +
-           (attr->mq_maxmsg * sizeof (struct msg_msg *)) <
+       if ((unsigned long)(attr->mq_maxmsg * (attr->mq_msgsize
+           + sizeof (struct msg_msg *))) <
            (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
                return 0;
        return 1;
@@ -623,9 +623,10 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
        int ret;
 
        if (attr) {
-               ret = -EINVAL;
-               if (!mq_attr_ok(ipc_ns, attr))
+               if (!mq_attr_ok(ipc_ns, attr)) {
+                       ret = -EINVAL;
                        goto out;
+               }
                /* store for use during create */
                dentry->d_fsdata = attr;
        }
@@ -659,24 +660,28 @@ out:
 static struct file *do_open(struct ipc_namespace *ipc_ns,
                                struct dentry *dentry, int oflag)
 {
+       int ret;
        const struct cred *cred = current_cred();
 
        static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
                                                  MAY_READ | MAY_WRITE };
 
        if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
-               dput(dentry);
-               mntput(ipc_ns->mq_mnt);
-               return ERR_PTR(-EINVAL);
+               ret = -EINVAL;
+               goto err;
        }
 
        if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
-               dput(dentry);
-               mntput(ipc_ns->mq_mnt);
-               return ERR_PTR(-EACCES);
+               ret = -EACCES;
+               goto err;
        }
 
        return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
+
+err:
+       dput(dentry);
+       mntput(ipc_ns->mq_mnt);
+       return ERR_PTR(ret);
 }
 
 SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
@@ -705,16 +710,17 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
        dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
        if (IS_ERR(dentry)) {
                error = PTR_ERR(dentry);
-               goto out_err;
+               goto out_putfd;
        }
        mntget(ipc_ns->mq_mnt);
 
        if (oflag & O_CREAT) {
                if (dentry->d_inode) {  /* entry already exists */
                        audit_inode(name, dentry);
-                       error = -EEXIST;
-                       if (oflag & O_EXCL)
+                       if (oflag & O_EXCL) {
+                               error = -EEXIST;
                                goto out;
+                       }
                        filp = do_open(ipc_ns, dentry, oflag);
                } else {
                        filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
@@ -722,9 +728,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
                                                u_attr ? &attr : NULL);
                }
        } else {
-               error = -ENOENT;
-               if (!dentry->d_inode)
+               if (!dentry->d_inode) {
+                       error = -ENOENT;
                        goto out;
+               }
                audit_inode(name, dentry);
                filp = do_open(ipc_ns, dentry, oflag);
        }
@@ -742,7 +749,6 @@ out:
        mntput(ipc_ns->mq_mnt);
 out_putfd:
        put_unused_fd(fd);
-out_err:
        fd = error;
 out_upsem:
        mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
@@ -872,19 +878,24 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
        audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
        timeout = prepare_timeout(p);
 
-       ret = -EBADF;
        filp = fget(mqdes);
-       if (unlikely(!filp))
+       if (unlikely(!filp)) {
+               ret = -EBADF;
                goto out;
+       }
 
        inode = filp->f_path.dentry->d_inode;
-       if (unlikely(filp->f_op != &mqueue_file_operations))
+       if (unlikely(filp->f_op != &mqueue_file_operations)) {
+               ret = -EBADF;
                goto out_fput;
+       }
        info = MQUEUE_I(inode);
        audit_inode(NULL, filp->f_path.dentry);
 
-       if (unlikely(!(filp->f_mode & FMODE_WRITE)))
+       if (unlikely(!(filp->f_mode & FMODE_WRITE))) {
+               ret = -EBADF;
                goto out_fput;
+       }
 
        if (unlikely(msg_len > info->attr.mq_msgsize)) {
                ret = -EMSGSIZE;
@@ -961,19 +972,24 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
        audit_mq_sendrecv(mqdes, msg_len, 0, p);
        timeout = prepare_timeout(p);
 
-       ret = -EBADF;
        filp = fget(mqdes);
-       if (unlikely(!filp))
+       if (unlikely(!filp)) {
+               ret = -EBADF;
                goto out;
+       }
 
        inode = filp->f_path.dentry->d_inode;
-       if (unlikely(filp->f_op != &mqueue_file_operations))
+       if (unlikely(filp->f_op != &mqueue_file_operations)) {
+               ret = -EBADF;
                goto out_fput;
+       }
        info = MQUEUE_I(inode);
        audit_inode(NULL, filp->f_path.dentry);
 
-       if (unlikely(!(filp->f_mode & FMODE_READ)))
+       if (unlikely(!(filp->f_mode & FMODE_READ))) {
+               ret = -EBADF;
                goto out_fput;
+       }
 
        /* checks if buffer is big enough */
        if (unlikely(msg_len < info->attr.mq_msgsize)) {
@@ -1063,13 +1079,14 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
 
                        /* create the notify skb */
                        nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
-                       ret = -ENOMEM;
-                       if (!nc)
+                       if (!nc) {
+                               ret = -ENOMEM;
                                goto out;
-                       ret = -EFAULT;
+                       }
                        if (copy_from_user(nc->data,
                                        notification.sigev_value.sival_ptr,
                                        NOTIFY_COOKIE_LEN)) {
+                               ret = -EFAULT;
                                goto out;
                        }
 
@@ -1078,9 +1095,10 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
                        /* and attach it to the socket */
 retry:
                        filp = fget(notification.sigev_signo);
-                       ret = -EBADF;
-                       if (!filp)
+                       if (!filp) {
+                               ret = -EBADF;
                                goto out;
+                       }
                        sock = netlink_getsockbyfilp(filp);
                        fput(filp);
                        if (IS_ERR(sock)) {
@@ -1092,7 +1110,7 @@ retry:
                        timeo = MAX_SCHEDULE_TIMEOUT;
                        ret = netlink_attachskb(sock, nc, &timeo, NULL);
                        if (ret == 1)
-                               goto retry;
+                               goto retry;
                        if (ret) {
                                sock = NULL;
                                nc = NULL;
@@ -1101,14 +1119,17 @@ retry:
                }
        }
 
-       ret = -EBADF;
        filp = fget(mqdes);
-       if (!filp)
+       if (!filp) {
+               ret = -EBADF;
                goto out;
+       }
 
        inode = filp->f_path.dentry->d_inode;
-       if (unlikely(filp->f_op != &mqueue_file_operations))
+       if (unlikely(filp->f_op != &mqueue_file_operations)) {
+               ret = -EBADF;
                goto out_fput;
+       }
        info = MQUEUE_I(inode);
 
        ret = 0;
@@ -1171,14 +1192,17 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
                        return -EINVAL;
        }
 
-       ret = -EBADF;
        filp = fget(mqdes);
-       if (!filp)
+       if (!filp) {
+               ret = -EBADF;
                goto out;
+       }
 
        inode = filp->f_path.dentry->d_inode;
-       if (unlikely(filp->f_op != &mqueue_file_operations))
+       if (unlikely(filp->f_op != &mqueue_file_operations)) {
+               ret = -EBADF;
                goto out_fput;
+       }
        info = MQUEUE_I(inode);
 
        spin_lock(&info->lock);
@@ -1272,7 +1296,7 @@ static int __init init_mqueue_fs(void)
        if (mqueue_inode_cachep == NULL)
                return -ENOMEM;
 
-       /* ignore failues - they are not fatal */
+       /* ignore failures - they are not fatal */
        mq_sysctl_table = mq_register_sysctl_table();
 
        error = register_filesystem(&mqueue_fs_type);
index 4b05bd9479dbc3d20cee5d658407d4cccb4a4727..028e85663f273d1d1cab2d75cde3ef76b22d3d48 100644 (file)
@@ -548,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule)
        return 0;
 }
 
+static int compare_root(struct vfsmount *mnt, void *arg)
+{
+       return mnt->mnt_root->d_inode == arg;
+}
+
 void audit_trim_trees(void)
 {
        struct list_head cursor;
@@ -559,7 +564,6 @@ void audit_trim_trees(void)
                struct path path;
                struct vfsmount *root_mnt;
                struct node *node;
-               struct list_head list;
                int err;
 
                tree = container_of(cursor.next, struct audit_tree, list);
@@ -577,24 +581,16 @@ void audit_trim_trees(void)
                if (!root_mnt)
                        goto skip_it;
 
-               list_add_tail(&list, &root_mnt->mnt_list);
                spin_lock(&hash_lock);
                list_for_each_entry(node, &tree->chunks, list) {
-                       struct audit_chunk *chunk = find_chunk(node);
-                       struct inode *inode = chunk->watch.inode;
-                       struct vfsmount *mnt;
+                       struct inode *inode = find_chunk(node)->watch.inode;
                        node->index |= 1U<<31;
-                       list_for_each_entry(mnt, &list, mnt_list) {
-                               if (mnt->mnt_root->d_inode == inode) {
-                                       node->index &= ~(1U<<31);
-                                       break;
-                               }
-                       }
+                       if (iterate_mounts(compare_root, inode, root_mnt))
+                               node->index &= ~(1U<<31);
                }
                spin_unlock(&hash_lock);
                trim_marked(tree);
                put_tree(tree);
-               list_del_init(&list);
                drop_collected_mounts(root_mnt);
 skip_it:
                mutex_lock(&audit_filter_mutex);
@@ -603,22 +599,6 @@ skip_it:
        mutex_unlock(&audit_filter_mutex);
 }
 
-static int is_under(struct vfsmount *mnt, struct dentry *dentry,
-                   struct path *path)
-{
-       if (mnt != path->mnt) {
-               for (;;) {
-                       if (mnt->mnt_parent == mnt)
-                               return 0;
-                       if (mnt->mnt_parent == path->mnt)
-                                       break;
-                       mnt = mnt->mnt_parent;
-               }
-               dentry = mnt->mnt_mountpoint;
-       }
-       return is_subdir(dentry, path->dentry);
-}
-
 int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
 {
 
@@ -638,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree)
        put_tree(tree);
 }
 
+static int tag_mount(struct vfsmount *mnt, void *arg)
+{
+       return tag_chunk(mnt->mnt_root->d_inode, arg);
+}
+
 /* called with audit_filter_mutex */
 int audit_add_tree_rule(struct audit_krule *rule)
 {
        struct audit_tree *seed = rule->tree, *tree;
        struct path path;
-       struct vfsmount *mnt, *p;
-       struct list_head list;
+       struct vfsmount *mnt;
        int err;
 
        list_for_each_entry(tree, &tree_list, list) {
@@ -670,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule)
                err = -ENOMEM;
                goto Err;
        }
-       list_add_tail(&list, &mnt->mnt_list);
 
        get_tree(tree);
-       list_for_each_entry(p, &list, mnt_list) {
-               err = tag_chunk(p->mnt_root->d_inode, tree);
-               if (err)
-                       break;
-       }
-
-       list_del(&list);
+       err = iterate_mounts(tag_mount, tree, mnt);
        drop_collected_mounts(mnt);
 
        if (!err) {
@@ -714,31 +691,23 @@ int audit_tag_tree(char *old, char *new)
 {
        struct list_head cursor, barrier;
        int failed = 0;
-       struct path path;
+       struct path path1, path2;
        struct vfsmount *tagged;
-       struct list_head list;
-       struct vfsmount *mnt;
-       struct dentry *dentry;
        int err;
 
-       err = kern_path(new, 0, &path);
+       err = kern_path(new, 0, &path2);
        if (err)
                return err;
-       tagged = collect_mounts(&path);
-       path_put(&path);
+       tagged = collect_mounts(&path2);
+       path_put(&path2);
        if (!tagged)
                return -ENOMEM;
 
-       err = kern_path(old, 0, &path);
+       err = kern_path(old, 0, &path1);
        if (err) {
                drop_collected_mounts(tagged);
                return err;
        }
-       mnt = mntget(path.mnt);
-       dentry = dget(path.dentry);
-       path_put(&path);
-
-       list_add_tail(&list, &tagged->mnt_list);
 
        mutex_lock(&audit_filter_mutex);
        list_add(&barrier, &tree_list);
@@ -746,7 +715,7 @@ int audit_tag_tree(char *old, char *new)
 
        while (cursor.next != &tree_list) {
                struct audit_tree *tree;
-               struct vfsmount *p;
+               int good_one = 0;
 
                tree = container_of(cursor.next, struct audit_tree, list);
                get_tree(tree);
@@ -754,30 +723,19 @@ int audit_tag_tree(char *old, char *new)
                list_add(&cursor, &tree->list);
                mutex_unlock(&audit_filter_mutex);
 
-               err = kern_path(tree->pathname, 0, &path);
-               if (err) {
-                       put_tree(tree);
-                       mutex_lock(&audit_filter_mutex);
-                       continue;
+               err = kern_path(tree->pathname, 0, &path2);
+               if (!err) {
+                       good_one = path_is_under(&path1, &path2);
+                       path_put(&path2);
                }
 
-               spin_lock(&vfsmount_lock);
-               if (!is_under(mnt, dentry, &path)) {
-                       spin_unlock(&vfsmount_lock);
-                       path_put(&path);
+               if (!good_one) {
                        put_tree(tree);
                        mutex_lock(&audit_filter_mutex);
                        continue;
                }
-               spin_unlock(&vfsmount_lock);
-               path_put(&path);
-
-               list_for_each_entry(p, &list, mnt_list) {
-                       failed = tag_chunk(p->mnt_root->d_inode, tree);
-                       if (failed)
-                               break;
-               }
 
+               failed = iterate_mounts(tag_mount, tree, tagged);
                if (failed) {
                        put_tree(tree);
                        mutex_lock(&audit_filter_mutex);
@@ -818,10 +776,8 @@ int audit_tag_tree(char *old, char *new)
        }
        list_del(&barrier);
        list_del(&cursor);
-       list_del(&list);
        mutex_unlock(&audit_filter_mutex);
-       dput(dentry);
-       mntput(mnt);
+       path_put(&path1);
        drop_collected_mounts(tagged);
        return failed;
 }
index fc0f928167e78b49d0a96b6a4f6e15e80ed90c6b..f3a461c0970a32b44fd8db7da5b50778b728ab88 100644 (file)
@@ -1988,7 +1988,6 @@ void __audit_inode(const char *name, const struct dentry *dentry)
 
 /**
  * audit_inode_child - collect inode info for created/removed objects
- * @dname: inode's dentry name
  * @dentry: dentry being audited
  * @parent: inode of dentry parent
  *
@@ -2000,13 +1999,14 @@ void __audit_inode(const char *name, const struct dentry *dentry)
  * must be hooked prior, in order to capture the target inode during
  * unsuccessful attempts.
  */
-void __audit_inode_child(const char *dname, const struct dentry *dentry,
+void __audit_inode_child(const struct dentry *dentry,
                         const struct inode *parent)
 {
        int idx;
        struct audit_context *context = current->audit_context;
        const char *found_parent = NULL, *found_child = NULL;
        const struct inode *inode = dentry->d_inode;
+       const char *dname = dentry->d_name.name;
        int dirlen = 0;
 
        if (!context->in_syscall)
@@ -2014,9 +2014,6 @@ void __audit_inode_child(const char *dname, const struct dentry *dentry,
 
        if (inode)
                handle_one(inode);
-       /* determine matching parent */
-       if (!dname)
-               goto add_names;
 
        /* parent is more likely, look for it first */
        for (idx = 0; idx < context->name_count; idx++) {
index 8f5d16e0707a403bac2f30887e3b43538328c825..8cd50d8f9bde4c2d2ce403736aa33c9b769f35c9 100644 (file)
@@ -1331,7 +1331,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
        ssize_t result;
        char *pathname;
        int flags;
-       int acc_mode, fmode;
+       int acc_mode;
 
        pathname = sysctl_getname(name, nlen, &table);
        result = PTR_ERR(pathname);
@@ -1342,15 +1342,12 @@ static ssize_t binary_sysctl(const int *name, int nlen,
        if (oldval && oldlen && newval && newlen) {
                flags = O_RDWR;
                acc_mode = MAY_READ | MAY_WRITE;
-               fmode = FMODE_READ | FMODE_WRITE;
        } else if (newval && newlen) {
                flags = O_WRONLY;
                acc_mode = MAY_WRITE;
-               fmode = FMODE_WRITE;
        } else if (oldval && oldlen) {
                flags = O_RDONLY;
                acc_mode = MAY_READ;
-               fmode = FMODE_READ;
        } else {
                result = 0;
                goto out_putname;
@@ -1361,7 +1358,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
        if (result)
                goto out_putname;
 
-       result = may_open(&nd.path, acc_mode, fmode);
+       result = may_open(&nd.path, acc_mode, flags);
        if (result)
                goto out_putpath;
 
index 698ea80f21022bf709dacc1101c614327109d828..148b52a5bb7e79e81aa1a1126baa9bafa97e073b 100644 (file)
@@ -1117,7 +1117,7 @@ readpage:
                        if (!PageUptodate(page)) {
                                if (page->mapping == NULL) {
                                        /*
-                                        * invalidate_inode_pages got it
+                                        * invalidate_mapping_pages got it
                                         */
                                        unlock_page(page);
                                        page_cache_release(page);
index 9ea45383480ee4ddc65711b0c3b45016ff048f0b..8d63f8fd29b7e3ff0e940d7457d45203f99c56b1 100644 (file)
@@ -999,19 +999,14 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
        inode = rpc_get_inode(sb, S_IFDIR | 0755);
        if (!inode)
                return -ENOMEM;
-       root = d_alloc_root(inode);
+       sb->s_root = root = d_alloc_root(inode);
        if (!root) {
                iput(inode);
                return -ENOMEM;
        }
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
-               goto out;
-       sb->s_root = root;
+               return -ENOMEM;
        return 0;
-out:
-       d_genocide(root);
-       dput(root);
-       return -ENOMEM;
 }
 
 static int
index a5721b373f53935601c63687acc5b4454acc54b4..5225e668dbf046fbe17ea105b23eb18cd11590d4 100644 (file)
@@ -387,7 +387,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags)
        struct smk_audit_info ad;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
-       smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_mountpoint);
+       smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root);
        smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
 
        sbp = mnt->mnt_sb->s_security;
index c00df45c7ede899681344086e509c52f4b180bc0..cf7d61f781b9768cc8691cd3b4fc4c234a313b55 100644 (file)
@@ -88,29 +88,14 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
                sp = dentry->d_op->d_dname(dentry, newname + offset,
                                           newname_len - offset);
        } else {
-               /* Taken from d_namespace_path(). */
-               struct path root;
-               struct path ns_root = { };
-               struct path tmp;
+               struct path ns_root = {.mnt = NULL, .dentry = NULL};
 
-               read_lock(&current->fs->lock);
-               root = current->fs->root;
-               path_get(&root);
-               read_unlock(&current->fs->lock);
-               spin_lock(&vfsmount_lock);
-               if (root.mnt && root.mnt->mnt_ns)
-                       ns_root.mnt = mntget(root.mnt->mnt_ns->root);
-               if (ns_root.mnt)
-                       ns_root.dentry = dget(ns_root.mnt->mnt_root);
-               spin_unlock(&vfsmount_lock);
                spin_lock(&dcache_lock);
-               tmp = ns_root;
-               sp = __d_path(path, &tmp, newname, newname_len);
+               /* go to whatever namespace root we are under */
+               sp = __d_path(path, &ns_root, newname, newname_len);
                spin_unlock(&dcache_lock);
-               path_put(&root);
-               path_put(&ns_root);
                /* Prepend "/proc" prefix if using internal proc vfs mount. */
-               if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
+               if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
                    (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
                        sp -= 5;
                        if (sp >= newname)