nfs: Fix misparsing of nfsv4 fs_locations attribute
[safe/jmp/linux-2.6] / fs / nfs / super.c
index e9b2017..20dc4cc 100644 (file)
@@ -91,6 +91,7 @@ enum {
        /* Mount options that take string arguments */
        Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
        Opt_addr, Opt_mountaddr, Opt_clientaddr,
+       Opt_lookupcache,
 
        /* Special mount options */
        Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -154,6 +155,8 @@ static match_table_t nfs_mount_option_tokens = {
        { Opt_mounthost, "mounthost=%s" },
        { Opt_mountaddr, "mountaddr=%s" },
 
+       { Opt_lookupcache, "lookupcache=%s" },
+
        { Opt_err, NULL }
 };
 
@@ -200,6 +203,22 @@ static match_table_t nfs_secflavor_tokens = {
        { Opt_sec_err, NULL }
 };
 
+enum {
+       Opt_lookupcache_all, Opt_lookupcache_positive,
+       Opt_lookupcache_none,
+
+       Opt_lookupcache_err
+};
+
+static match_table_t nfs_lookupcache_tokens = {
+       { Opt_lookupcache_all, "all" },
+       { Opt_lookupcache_positive, "pos" },
+       { Opt_lookupcache_positive, "positive" },
+       { Opt_lookupcache_none, "none" },
+
+       { Opt_lookupcache_err, NULL }
+};
+
 
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
@@ -209,7 +228,6 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru
 static int nfs_xdev_get_sb(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
 static void nfs_kill_super(struct super_block *);
-static void nfs_put_super(struct super_block *);
 static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 
 static struct file_system_type nfs_fs_type = {
@@ -232,7 +250,6 @@ static const struct super_operations nfs_sops = {
        .alloc_inode    = nfs_alloc_inode,
        .destroy_inode  = nfs_destroy_inode,
        .write_inode    = nfs_write_inode,
-       .put_super      = nfs_put_super,
        .statfs         = nfs_statfs,
        .clear_inode    = nfs_clear_inode,
        .umount_begin   = nfs_umount_begin,
@@ -337,26 +354,20 @@ void __exit unregister_nfs_fs(void)
        unregister_filesystem(&nfs_fs_type);
 }
 
-void nfs_sb_active(struct nfs_server *server)
+void nfs_sb_active(struct super_block *sb)
 {
-       atomic_inc(&server->active);
-}
+       struct nfs_server *server = NFS_SB(sb);
 
-void nfs_sb_deactive(struct nfs_server *server)
-{
-       if (atomic_dec_and_test(&server->active))
-               wake_up(&server->active_wq);
+       if (atomic_inc_return(&server->active) == 1)
+               atomic_inc(&sb->s_active);
 }
 
-static void nfs_put_super(struct super_block *sb)
+void nfs_sb_deactive(struct super_block *sb)
 {
        struct nfs_server *server = NFS_SB(sb);
-       /*
-        * Make sure there are no outstanding ops to this server.
-        * If so, wait for them to finish before allowing the
-        * unmount to continue.
-        */
-       wait_event(server->active_wq, atomic_read(&server->active) == 0);
+
+       if (atomic_dec_and_test(&server->active))
+               deactivate_super(sb);
 }
 
 /*
@@ -664,25 +675,6 @@ static void nfs_umount_begin(struct super_block *sb)
 }
 
 /*
- * Set the port number in an address.  Be agnostic about the address family.
- */
-static void nfs_set_port(struct sockaddr *sap, unsigned short port)
-{
-       switch (sap->sa_family) {
-       case AF_INET: {
-               struct sockaddr_in *ap = (struct sockaddr_in *)sap;
-               ap->sin_port = htons(port);
-               break;
-       }
-       case AF_INET6: {
-               struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
-               ap->sin6_port = htons(port);
-               break;
-       }
-       }
-}
-
-/*
  * Sanity-check a server address provided by the mount command.
  *
  * Address family must be initialized, and address must not be
@@ -724,8 +716,6 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
        *addr_len = 0;
 }
 
-#define IPV6_SCOPE_DELIMITER   '%'
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
                                    const char *delim,
@@ -798,7 +788,7 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
  * If there is a problem constructing the new sockaddr, set the address
  * family to AF_UNSPEC.
  */
-static void nfs_parse_ip_address(char *string, size_t str_len,
+void nfs_parse_ip_address(char *string, size_t str_len,
                                 struct sockaddr *sap, size_t *addr_len)
 {
        unsigned int i, colons;
@@ -1258,6 +1248,30 @@ static int nfs_parse_mount_options(char *raw,
                                             &mnt->mount_server.addrlen);
                        kfree(string);
                        break;
+               case Opt_lookupcache:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string,
+                                       nfs_lookupcache_tokens, args);
+                       kfree(string);
+                       switch (token) {
+                               case Opt_lookupcache_all:
+                                       mnt->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
+                                       break;
+                               case Opt_lookupcache_positive:
+                                       mnt->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
+                                       mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
+                                       break;
+                               case Opt_lookupcache_none:
+                                       mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
+                                       break;
+                               default:
+                                       errors++;
+                                       dfprintk(MOUNT, "NFS:   invalid "
+                                                       "lookupcache argument\n");
+                       };
+                       break;
 
                /*
                 * Special options
@@ -1558,7 +1572,7 @@ static int nfs_validate_mount_data(void *options,
                 * Translate to nfs_parsed_mount_data, which nfs_fill_super
                 * can deal with.
                 */
-               args->flags             = data->flags;
+               args->flags             = data->flags & NFS_MOUNT_FLAGMASK;
                args->rsize             = data->rsize;
                args->wsize             = data->wsize;
                args->timeo             = data->timeo;