]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
Merge branch 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jan 2010 22:03:55 +0000 (14:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jan 2010 22:03:55 +0000 (14:03 -0800)
* 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing:
  reiserfs: Relax reiserfs_xattr_set_handle() while acquiring xattr locks
  reiserfs: Fix unreachable statement
  reiserfs: Don't call reiserfs_get_acl() with the reiserfs lock
  reiserfs: Relax lock on xattr removing
  reiserfs: Relax the lock before truncating pages
  reiserfs: Fix recursive lock on lchown
  reiserfs: Fix mistake in down_write() conversion

1  2 
fs/reiserfs/inode.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_acl.c

diff --combined fs/reiserfs/inode.c
index 1150ebb2536fd0fad8aa2ed9bdb27c557e95fb20,c876341ea73848b791ce1a99b330076ce1ebd91c..9087b10209e634c4f694aceaad2e14bde7e01ba2
@@@ -2539,12 -2539,6 +2539,12 @@@ static int reiserfs_writepage(struct pa
        return reiserfs_write_full_page(page, wbc);
  }
  
 +static void reiserfs_truncate_failed_write(struct inode *inode)
 +{
 +      truncate_inode_pages(inode->i_mapping, inode->i_size);
 +      reiserfs_truncate_file(inode, 0);
 +}
 +
  static int reiserfs_write_begin(struct file *file,
                                struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
        if (ret) {
                unlock_page(page);
                page_cache_release(page);
 +              /* Truncate allocated blocks */
 +              reiserfs_truncate_failed_write(inode);
        }
        return ret;
  }
@@@ -2710,7 -2702,9 +2710,7 @@@ static int reiserfs_write_end(struct fi
         ** transaction tracking stuff when the size changes.  So, we have
         ** to do the i_size updates here.
         */
 -      pos += copied;
 -
 -      if (pos > inode->i_size) {
 +      if (pos + copied > inode->i_size) {
                struct reiserfs_transaction_handle myth;
                lock_depth = reiserfs_write_lock_once(inode->i_sb);
                locked = true;
                        goto journal_error;
  
                reiserfs_update_inode_transaction(inode);
 -              inode->i_size = pos;
 +              inode->i_size = pos + copied;
                /*
                 * this will just nest into our transaction.  It's important
                 * to use mark_inode_dirty so the inode gets pushed around on the
                reiserfs_write_unlock_once(inode->i_sb, lock_depth);
        unlock_page(page);
        page_cache_release(page);
 +
 +      if (pos + len > inode->i_size)
 +              reiserfs_truncate_failed_write(inode);
 +
        return ret == 0 ? copied : ret;
  
        journal_error:
@@@ -3062,13 -3052,14 +3062,14 @@@ static ssize_t reiserfs_direct_IO(int r
  int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
  {
        struct inode *inode = dentry->d_inode;
-       int error;
        unsigned int ia_valid;
+       int depth;
+       int error;
  
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
  
-       reiserfs_write_lock(inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
                                    journal_end(&th, inode->i_sb, jbegin_count);
                        }
                }
-               if (!error)
+               if (!error) {
+                       /*
+                        * Relax the lock here, as it might truncate the
+                        * inode pages and wait for inode pages locks.
+                        * To release such page lock, the owner needs the
+                        * reiserfs lock
+                        */
+                       reiserfs_write_unlock_once(inode->i_sb, depth);
                        error = inode_setattr(inode, attr);
+                       depth = reiserfs_write_lock_once(inode->i_sb);
+               }
        }
  
        if (!error && reiserfs_posixacl(inode->i_sb)) {
        }
  
        out:
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
        return error;
  }
  
diff --combined fs/reiserfs/xattr.c
index c3b004ee627b34ec23c459b3e8178b6b166c6fd1,7fee995c25ab2f6cc0e0e70be44549aeb2087fd1..81f09fab8ae476ccbdb9547d226e397e1b8cb6d1
@@@ -48,7 -48,6 +48,7 @@@
  #include <net/checksum.h>
  #include <linux/stat.h>
  #include <linux/quotaops.h>
 +#include <linux/security.h>
  
  #define PRIVROOT_NAME ".reiserfs_priv"
  #define XAROOT_NAME   "xattrs"
@@@ -452,7 -451,9 +452,9 @@@ static int lookup_and_delete_xattr(stru
        }
  
        if (dentry->d_inode) {
+               reiserfs_write_lock(inode->i_sb);
                err = xattr_unlink(xadir->d_inode, dentry);
+               reiserfs_write_unlock(inode->i_sb);
                update_ctime(inode);
        }
  
@@@ -486,17 -487,21 +488,21 @@@ reiserfs_xattr_set_handle(struct reiser
        if (get_inode_sd_version(inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
  
-       if (!buffer)
-               return lookup_and_delete_xattr(inode, name);
        reiserfs_write_unlock(inode->i_sb);
+       if (!buffer) {
+               err = lookup_and_delete_xattr(inode, name);
+               reiserfs_write_lock(inode->i_sb);
+               return err;
+       }
        dentry = xattr_lookup(inode, name, flags);
        if (IS_ERR(dentry)) {
                reiserfs_write_lock(inode->i_sb);
                return PTR_ERR(dentry);
        }
  
-       down_read(&REISERFS_I(inode)->i_xattr_sem);
+       down_write(&REISERFS_I(inode)->i_xattr_sem);
  
        reiserfs_write_lock(inode->i_sb);
  
                        .ia_size = buffer_size,
                        .ia_valid = ATTR_SIZE | ATTR_CTIME,
                };
+               reiserfs_write_unlock(inode->i_sb);
                mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
                down_write(&dentry->d_inode->i_alloc_sem);
+               reiserfs_write_lock(inode->i_sb);
                err = reiserfs_setattr(dentry, &newattrs);
                up_write(&dentry->d_inode->i_alloc_sem);
                mutex_unlock(&dentry->d_inode->i_mutex);
@@@ -741,14 -750,15 +751,14 @@@ ssize_
  reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
                  size_t size)
  {
 -      struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
  
 -      handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
 +      handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
  
 -      if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 +      if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
  
 -      return handler->get(inode, name, buffer, size);
 +      return handler->get(dentry, name, buffer, size, handler->flags);
  }
  
  /*
@@@ -760,14 -770,15 +770,14 @@@ in
  reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags)
  {
 -      struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
  
 -      handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
 +      handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
  
 -      if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 +      if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
  
 -      return handler->set(inode, name, value, size, flags);
 +      return handler->set(dentry, name, value, size, flags, handler->flags);
  }
  
  /*
   */
  int reiserfs_removexattr(struct dentry *dentry, const char *name)
  {
 -      struct inode *inode = dentry->d_inode;
        struct xattr_handler *handler;
 -      handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
 +      handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
  
 -      if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 +      if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
  
 -      return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
 +      return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
  }
  
  struct listxattr_buf {
        size_t size;
        size_t pos;
        char *buf;
 -      struct inode *inode;
 +      struct dentry *dentry;
  };
  
  static int listxattr_filler(void *buf, const char *name, int namelen,
        if (name[0] != '.' ||
            (namelen != 1 && (name[1] != '.' || namelen != 2))) {
                struct xattr_handler *handler;
 -              handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
 +              handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
                                                    name);
                if (!handler)   /* Unsupported xattr name */
                        return 0;
                if (b->buf) {
 -                      size = handler->list(b->inode, b->buf + b->pos,
 -                                       b->size, name, namelen);
 +                      size = handler->list(b->dentry, b->buf + b->pos,
 +                                       b->size, name, namelen,
 +                                       handler->flags);
                        if (size > b->size)
                                return -ERANGE;
                } else {
 -                      size = handler->list(b->inode, NULL, 0, name, namelen);
 +                      size = handler->list(b->dentry, NULL, 0, name,
 +                                           namelen, handler->flags);
                }
  
                b->pos += size;
@@@ -834,7 -844,7 +844,7 @@@ ssize_t reiserfs_listxattr(struct dentr
        int err = 0;
        loff_t pos = 0;
        struct listxattr_buf buf = {
 -              .inode = dentry->d_inode,
 +              .dentry = dentry,
                .buf = buffer,
                .size = buffer ? size : 0,
        };
diff --combined fs/reiserfs/xattr_acl.c
index cc32e6ada67b3330aa0a9e3fc3bacfd0ca7c7c61,f559c9e1efc888cb35527a02ceb267c83be62362..dd20a7883f0f3a2606d3b4d8bf9ca2a65f274fbb
@@@ -15,10 -15,8 +15,10 @@@ static int reiserfs_set_acl(struct reis
                            struct posix_acl *acl);
  
  static int
 -xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
 +posix_acl_set(struct dentry *dentry, const char *name, const void *value,
 +              size_t size, int flags, int type)
  {
 +      struct inode *inode = dentry->d_inode;
        struct posix_acl *acl;
        int error, error2;
        struct reiserfs_transaction_handle th;
  }
  
  static int
 -xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
 +posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
 +              size_t size, int type)
  {
        struct posix_acl *acl;
        int error;
  
 -      if (!reiserfs_posixacl(inode->i_sb))
 +      if (!reiserfs_posixacl(dentry->d_sb))
                return -EOPNOTSUPP;
  
 -      acl = reiserfs_get_acl(inode, type);
 +      acl = reiserfs_get_acl(dentry->d_inode, type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@@ -455,7 -452,9 +455,9 @@@ int reiserfs_acl_chmod(struct inode *in
                return 0;
        }
  
+       reiserfs_write_unlock(inode->i_sb);
        acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
+       reiserfs_write_lock(inode->i_sb);
        if (!acl)
                return 0;
        if (IS_ERR(acl))
        return error;
  }
  
 -static int
 -posix_acl_access_get(struct inode *inode, const char *name,
 -                   void *buffer, size_t size)
 -{
 -      if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
 -              return -EINVAL;
 -      return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
 -}
 -
 -static int
 -posix_acl_access_set(struct inode *inode, const char *name,
 -                   const void *value, size_t size, int flags)
 -{
 -      if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
 -              return -EINVAL;
 -      return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
 -}
 -
 -static size_t posix_acl_access_list(struct inode *inode, char *list,
 +static size_t posix_acl_access_list(struct dentry *dentry, char *list,
                                    size_t list_size, const char *name,
 -                                  size_t name_len)
 +                                  size_t name_len, int type)
  {
        const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 -      if (!reiserfs_posixacl(inode->i_sb))
 +      if (!reiserfs_posixacl(dentry->d_sb))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
  
  struct xattr_handler reiserfs_posix_acl_access_handler = {
        .prefix = POSIX_ACL_XATTR_ACCESS,
 -      .get = posix_acl_access_get,
 -      .set = posix_acl_access_set,
 +      .flags = ACL_TYPE_ACCESS,
 +      .get = posix_acl_get,
 +      .set = posix_acl_set,
        .list = posix_acl_access_list,
  };
  
 -static int
 -posix_acl_default_get(struct inode *inode, const char *name,
 -                    void *buffer, size_t size)
 -{
 -      if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
 -              return -EINVAL;
 -      return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
 -}
 -
 -static int
 -posix_acl_default_set(struct inode *inode, const char *name,
 -                    const void *value, size_t size, int flags)
 -{
 -      if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
 -              return -EINVAL;
 -      return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
 -}
 -
 -static size_t posix_acl_default_list(struct inode *inode, char *list,
 +static size_t posix_acl_default_list(struct dentry *dentry, char *list,
                                     size_t list_size, const char *name,
 -                                   size_t name_len)
 +                                   size_t name_len, int type)
  {
        const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 -      if (!reiserfs_posixacl(inode->i_sb))
 +      if (!reiserfs_posixacl(dentry->d_sb))
                return 0;
        if (list && size <= list_size)
                memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
  
  struct xattr_handler reiserfs_posix_acl_default_handler = {
        .prefix = POSIX_ACL_XATTR_DEFAULT,
 -      .get = posix_acl_default_get,
 -      .set = posix_acl_default_set,
 +      .flags = ACL_TYPE_DEFAULT,
 +      .get = posix_acl_get,
 +      .set = posix_acl_set,
        .list = posix_acl_default_list,
  };