Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Oct 2016 22:15:33 +0000 (15:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Oct 2016 22:15:33 +0000 (15:15 -0700)
Pull ext4 updates from Ted Ts'o:
 "Lots of bug fixes and cleanups"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (40 commits)
  ext4: remove unused variable
  ext4: use journal inode to determine journal overhead
  ext4: create function to read journal inode
  ext4: unmap metadata when zeroing blocks
  ext4: remove plugging from ext4_file_write_iter()
  ext4: allow unlocked direct IO when pages are cached
  ext4: require encryption feature for EXT4_IOC_SET_ENCRYPTION_POLICY
  fscrypto: use standard macros to compute length of fname ciphertext
  ext4: do not unnecessarily null-terminate encrypted symlink data
  ext4: release bh in make_indexed_dir
  ext4: Allow parallel DIO reads
  ext4: allow DAX writeback for hole punch
  jbd2: fix lockdep annotation in add_transaction_credits()
  blockgroup_lock.h: simplify definition of NR_BG_LOCKS
  blockgroup_lock.h: remove debris from bgl_lock_ptr() conversion
  fscrypto: make filename crypto functions return 0 on success
  fscrypto: rename completion callbacks to reflect usage
  fscrypto: remove unnecessary includes
  fscrypto: improved validation when loading inode encryption metadata
  ext4: fix memory leak when symlink decryption fails
  ...

24 files changed:
fs/crypto/crypto.c
fs/crypto/fname.c
fs/crypto/keyinfo.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/move_extent.c
fs/ext4/namei.c
fs/ext4/page-io.c
fs/ext4/super.c
fs/ext4/symlink.c
fs/ext4/xattr.c
fs/f2fs/dir.c
fs/f2fs/namei.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/mbcache.c
include/linux/blockgroup_lock.h
include/linux/fscrypto.h

index c502c11..61057b7 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/fscrypto.h>
-#include <linux/ecryptfs.h>
 
 static unsigned int num_prealloc_crypto_pages = 32;
 static unsigned int num_prealloc_crypto_ctxs = 128;
@@ -128,11 +127,11 @@ struct fscrypt_ctx *fscrypt_get_ctx(struct inode *inode, gfp_t gfp_flags)
 EXPORT_SYMBOL(fscrypt_get_ctx);
 
 /**
- * fscrypt_complete() - The completion callback for page encryption
- * @req: The asynchronous encryption request context
- * @res: The result of the encryption operation
+ * page_crypt_complete() - completion callback for page crypto
+ * @req: The asynchronous cipher request context
+ * @res: The result of the cipher operation
  */
-static void fscrypt_complete(struct crypto_async_request *req, int res)
+static void page_crypt_complete(struct crypto_async_request *req, int res)
 {
        struct fscrypt_completion_result *ecr = req->data;
 
@@ -170,7 +169,7 @@ static int do_page_crypto(struct inode *inode,
 
        skcipher_request_set_callback(
                req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-               fscrypt_complete, &ecr);
+               page_crypt_complete, &ecr);
 
        BUILD_BUG_ON(FS_XTS_TWEAK_SIZE < sizeof(index));
        memcpy(xts_tweak, &index, sizeof(index));
index 5d6d491..9a28133 100644 (file)
  * This has not yet undergone a rigorous security audit.
  */
 
-#include <keys/encrypted-type.h>
-#include <keys/user-type.h>
 #include <linux/scatterlist.h>
 #include <linux/ratelimit.h>
 #include <linux/fscrypto.h>
 
-static u32 size_round_up(size_t size, size_t blksize)
-{
-       return ((size + blksize - 1) / blksize) * blksize;
-}
-
 /**
- * dir_crypt_complete() -
+ * fname_crypt_complete() - completion callback for filename crypto
+ * @req: The asynchronous cipher request context
+ * @res: The result of the cipher operation
  */
-static void dir_crypt_complete(struct crypto_async_request *req, int res)
+static void fname_crypt_complete(struct crypto_async_request *req, int res)
 {
        struct fscrypt_completion_result *ecr = req->data;
 
@@ -35,11 +30,11 @@ static void dir_crypt_complete(struct crypto_async_request *req, int res)
 }
 
 /**
- * fname_encrypt() -
+ * fname_encrypt() - encrypt a filename
  *
- * This function encrypts the input filename, and returns the length of the
- * ciphertext. Errors are returned as negative numbers.  We trust the caller to
- * allocate sufficient memory to oname string.
+ * The caller must have allocated sufficient memory for the @oname string.
+ *
+ * Return: 0 on success, -errno on failure
  */
 static int fname_encrypt(struct inode *inode,
                        const struct qstr *iname, struct fscrypt_str *oname)
@@ -60,10 +55,9 @@ static int fname_encrypt(struct inode *inode,
        if (iname->len <= 0 || iname->len > lim)
                return -EIO;
 
-       ciphertext_len = (iname->len < FS_CRYPTO_BLOCK_SIZE) ?
-                                       FS_CRYPTO_BLOCK_SIZE : iname->len;
-       ciphertext_len = size_round_up(ciphertext_len, padding);
-       ciphertext_len = (ciphertext_len > lim) ? lim : ciphertext_len;
+       ciphertext_len = max(iname->len, (u32)FS_CRYPTO_BLOCK_SIZE);
+       ciphertext_len = round_up(ciphertext_len, padding);
+       ciphertext_len = min(ciphertext_len, lim);
 
        if (ciphertext_len <= sizeof(buf)) {
                workbuf = buf;
@@ -84,7 +78,7 @@ static int fname_encrypt(struct inode *inode,
        }
        skcipher_request_set_callback(req,
                        CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-                       dir_crypt_complete, &ecr);
+                       fname_crypt_complete, &ecr);
 
        /* Copy the input */
        memcpy(workbuf, iname->name, iname->len);
@@ -105,20 +99,22 @@ static int fname_encrypt(struct inode *inode,
        }
        kfree(alloc_buf);
        skcipher_request_free(req);
-       if (res < 0)
+       if (res < 0) {
                printk_ratelimited(KERN_ERR
                                "%s: Error (error code %d)\n", __func__, res);
+               return res;
+       }
 
        oname->len = ciphertext_len;
-       return res;
+       return 0;
 }
 
-/*
- * fname_decrypt()
- *     This function decrypts the input filename, and returns
- *     the length of the plaintext.
- *     Errors are returned as negative numbers.
- *     We trust the caller to allocate sufficient memory to oname string.
+/**
+ * fname_decrypt() - decrypt a filename
+ *
+ * The caller must have allocated sufficient memory for the @oname string.
+ *
+ * Return: 0 on success, -errno on failure
  */
 static int fname_decrypt(struct inode *inode,
                                const struct fscrypt_str *iname,
@@ -146,7 +142,7 @@ static int fname_decrypt(struct inode *inode,
        }
        skcipher_request_set_callback(req,
                CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-               dir_crypt_complete, &ecr);
+               fname_crypt_complete, &ecr);
 
        /* Initialize IV */
        memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
@@ -168,7 +164,7 @@ static int fname_decrypt(struct inode *inode,
        }
 
        oname->len = strnlen(oname->name, iname->len);
-       return oname->len;
+       return 0;
 }
 
 static const char *lookup_table =
@@ -231,9 +227,8 @@ u32 fscrypt_fname_encrypted_size(struct inode *inode, u32 ilen)
 
        if (ci)
                padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK);
-       if (ilen < FS_CRYPTO_BLOCK_SIZE)
-               ilen = FS_CRYPTO_BLOCK_SIZE;
-       return size_round_up(ilen, padding);
+       ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE);
+       return round_up(ilen, padding);
 }
 EXPORT_SYMBOL(fscrypt_fname_encrypted_size);
 
@@ -279,6 +274,10 @@ EXPORT_SYMBOL(fscrypt_fname_free_buffer);
 /**
  * fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
  * space
+ *
+ * The caller must have allocated sufficient memory for the @oname string.
+ *
+ * Return: 0 on success, -errno on failure
  */
 int fscrypt_fname_disk_to_usr(struct inode *inode,
                        u32 hash, u32 minor_hash,
@@ -287,13 +286,12 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
 {
        const struct qstr qname = FSTR_TO_QSTR(iname);
        char buf[24];
-       int ret;
 
        if (fscrypt_is_dot_dotdot(&qname)) {
                oname->name[0] = '.';
                oname->name[iname->len - 1] = '.';
                oname->len = iname->len;
-               return oname->len;
+               return 0;
        }
 
        if (iname->len < FS_CRYPTO_BLOCK_SIZE)
@@ -303,9 +301,9 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
                return fname_decrypt(inode, iname, oname);
 
        if (iname->len <= FS_FNAME_CRYPTO_DIGEST_SIZE) {
-               ret = digest_encode(iname->name, iname->len, oname->name);
-               oname->len = ret;
-               return ret;
+               oname->len = digest_encode(iname->name, iname->len,
+                                          oname->name);
+               return 0;
        }
        if (hash) {
                memcpy(buf, &hash, 4);
@@ -315,15 +313,18 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
        }
        memcpy(buf + 8, iname->name + iname->len - 16, 16);
        oname->name[0] = '_';
-       ret = digest_encode(buf, 24, oname->name + 1);
-       oname->len = ret + 1;
-       return ret + 1;
+       oname->len = 1 + digest_encode(buf, 24, oname->name + 1);
+       return 0;
 }
 EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
 
 /**
  * fscrypt_fname_usr_to_disk() - converts a filename from user space to disk
  * space
+ *
+ * The caller must have allocated sufficient memory for the @oname string.
+ *
+ * Return: 0 on success, -errno on failure
  */
 int fscrypt_fname_usr_to_disk(struct inode *inode,
                        const struct qstr *iname,
@@ -333,7 +334,7 @@ int fscrypt_fname_usr_to_disk(struct inode *inode,
                oname->name[0] = '.';
                oname->name[iname->len - 1] = '.';
                oname->len = iname->len;
-               return oname->len;
+               return 0;
        }
        if (inode->i_crypt_info)
                return fname_encrypt(inode, iname, oname);
@@ -367,10 +368,10 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
        if (dir->i_crypt_info) {
                ret = fscrypt_fname_alloc_buffer(dir, iname->len,
                                                        &fname->crypto_buf);
-               if (ret < 0)
+               if (ret)
                        return ret;
                ret = fname_encrypt(dir, iname, &fname->crypto_buf);
-               if (ret < 0)
+               if (ret)
                        goto errout;
                fname->disk_name.name = fname->crypto_buf.name;
                fname->disk_name.len = fname->crypto_buf.len;
index 1ac263e..82f0285 100644 (file)
@@ -8,11 +8,8 @@
  * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
  */
 
-#include <keys/encrypted-type.h>
 #include <keys/user-type.h>
-#include <linux/random.h>
 #include <linux/scatterlist.h>
-#include <uapi/linux/keyctl.h>
 #include <linux/fscrypto.h>
 
 static void derive_crypt_complete(struct crypto_async_request *req, int rc)
@@ -139,6 +136,38 @@ out:
        return res;
 }
 
+static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode,
+                                const char **cipher_str_ret, int *keysize_ret)
+{
+       if (S_ISREG(inode->i_mode)) {
+               if (ci->ci_data_mode == FS_ENCRYPTION_MODE_AES_256_XTS) {
+                       *cipher_str_ret = "xts(aes)";
+                       *keysize_ret = FS_AES_256_XTS_KEY_SIZE;
+                       return 0;
+               }
+               pr_warn_once("fscrypto: unsupported contents encryption mode "
+                            "%d for inode %lu\n",
+                            ci->ci_data_mode, inode->i_ino);
+               return -ENOKEY;
+       }
+
+       if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
+               if (ci->ci_filename_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
+                       *cipher_str_ret = "cts(cbc(aes))";
+                       *keysize_ret = FS_AES_256_CTS_KEY_SIZE;
+                       return 0;
+               }
+               pr_warn_once("fscrypto: unsupported filenames encryption mode "
+                            "%d for inode %lu\n",
+                            ci->ci_filename_mode, inode->i_ino);
+               return -ENOKEY;
+       }
+
+       pr_warn_once("fscrypto: unsupported file type %d for inode %lu\n",
+                    (inode->i_mode & S_IFMT), inode->i_ino);
+       return -ENOKEY;
+}
+
 static void put_crypt_info(struct fscrypt_info *ci)
 {
        if (!ci)
@@ -155,8 +184,8 @@ int get_crypt_info(struct inode *inode)
        struct fscrypt_context ctx;
        struct crypto_skcipher *ctfm;
        const char *cipher_str;
+       int keysize;
        u8 raw_key[FS_MAX_KEY_SIZE];
-       u8 mode;
        int res;
 
        res = fscrypt_initialize();
@@ -179,13 +208,19 @@ retry:
        if (res < 0) {
                if (!fscrypt_dummy_context_enabled(inode))
                        return res;
+               ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
                ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
                ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
                ctx.flags = 0;
        } else if (res != sizeof(ctx)) {
                return -EINVAL;
        }
-       res = 0;
+
+       if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
+               return -EINVAL;
+
+       if (ctx.flags & ~FS_POLICY_FLAGS_VALID)
+               return -EINVAL;
 
        crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS);
        if (!crypt_info)
@@ -198,27 +233,11 @@ retry:
        crypt_info->ci_keyring_key = NULL;
        memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
                                sizeof(crypt_info->ci_master_key));
-       if (S_ISREG(inode->i_mode))
-               mode = crypt_info->ci_data_mode;
-       else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-               mode = crypt_info->ci_filename_mode;
-       else
-               BUG();
-
-       switch (mode) {
-       case FS_ENCRYPTION_MODE_AES_256_XTS:
-               cipher_str = "xts(aes)";
-               break;
-       case FS_ENCRYPTION_MODE_AES_256_CTS:
-               cipher_str = "cts(cbc(aes))";
-               break;
-       default:
-               printk_once(KERN_WARNING
-                           "%s: unsupported key mode %d (ino %u)\n",
-                           __func__, mode, (unsigned) inode->i_ino);
-               res = -ENOKEY;
+
+       res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize);
+       if (res)
                goto out;
-       }
+
        if (fscrypt_dummy_context_enabled(inode)) {
                memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
                goto got_key;
@@ -253,7 +272,7 @@ got_key:
        crypt_info->ci_ctfm = ctfm;
        crypto_skcipher_clear_flags(ctfm, ~0);
        crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY);
-       res = crypto_skcipher_setkey(ctfm, raw_key, fscrypt_key_size(mode));
+       res = crypto_skcipher_setkey(ctfm, raw_key, keysize);
        if (res)
                goto out;
 
index 67415e0..e8b3650 100644 (file)
@@ -260,11 +260,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                                        /* Directory is encrypted */
                                        err = fscrypt_fname_disk_to_usr(inode,
                                                0, 0, &de_name, &fstr);
+                                       de_name = fstr;
                                        fstr.len = save_len;
-                                       if (err < 0)
+                                       if (err)
                                                goto errout;
                                        if (!dir_emit(ctx,
-                                           fstr.name, err,
+                                           de_name.name, de_name.len,
                                            le32_to_cpu(de->inode),
                                            get_dtype(sb, de->file_type)))
                                                goto done;
@@ -627,7 +628,7 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
                      int buf_size)
 {
        struct ext4_dir_entry_2 *de;
-       int nlen, rlen;
+       int rlen;
        unsigned int offset = 0;
        char *top;
 
@@ -637,7 +638,6 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
                if (ext4_check_dir_entry(dir, NULL, de, bh,
                                         buf, buf_size, offset))
                        return -EFSCORRUPTED;
-               nlen = EXT4_DIR_REC_LEN(de->name_len);
                rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
                de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
                offset += rlen;
index ea31931..282a51b 100644 (file)
@@ -262,6 +262,9 @@ struct ext4_io_submit {
                                 (s)->s_first_ino)
 #endif
 #define EXT4_BLOCK_ALIGN(size, blkbits)                ALIGN((size), (1 << (blkbits)))
+#define EXT4_MAX_BLOCKS(size, offset, blkbits) \
+       ((EXT4_BLOCK_ALIGN(size + offset, blkbits) >> blkbits) - (offset >> \
+                                                                 blkbits))
 
 /* Translate a block number to a cluster number */
 #define EXT4_B2C(sbi, blk)     ((blk) >> (sbi)->s_cluster_bits)
@@ -1117,9 +1120,15 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_POSIX_ACL           0x08000 /* POSIX Access Control Lists */
 #define EXT4_MOUNT_NO_AUTO_DA_ALLOC    0x10000 /* No auto delalloc mapping */
 #define EXT4_MOUNT_BARRIER             0x20000 /* Use block barriers */
-#define EXT4_MOUNT_QUOTA               0x80000 /* Some quota option set */
-#define EXT4_MOUNT_USRQUOTA            0x100000 /* "old" user quota */
-#define EXT4_MOUNT_GRPQUOTA            0x200000 /* "old" group quota */
+#define EXT4_MOUNT_QUOTA               0x40000 /* Some quota option set */
+#define EXT4_MOUNT_USRQUOTA            0x80000 /* "old" user quota,
+                                                * enable enforcement for hidden
+                                                * quota files */
+#define EXT4_MOUNT_GRPQUOTA            0x100000 /* "old" group quota, enable
+                                                 * enforcement for hidden quota
+                                                 * files */
+#define EXT4_MOUNT_PRJQUOTA            0x200000 /* Enable project quota
+                                                 * enforcement */
 #define EXT4_MOUNT_DIOREAD_NOLOCK      0x400000 /* Enable support for dio read nolocking */
 #define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
@@ -1636,26 +1645,6 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
  * Feature set definitions
  */
 
-/* Use the ext4_{has,set,clear}_feature_* helpers; these will be removed */
-#define EXT4_HAS_COMPAT_FEATURE(sb,mask)                       \
-       ((EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask)) != 0)
-#define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask)                    \
-       ((EXT4_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask)) != 0)
-#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask)                     \
-       ((EXT4_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask)) != 0)
-#define EXT4_SET_COMPAT_FEATURE(sb,mask)                       \
-       EXT4_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
-#define EXT4_SET_RO_COMPAT_FEATURE(sb,mask)                    \
-       EXT4_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
-#define EXT4_SET_INCOMPAT_FEATURE(sb,mask)                     \
-       EXT4_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
-#define EXT4_CLEAR_COMPAT_FEATURE(sb,mask)                     \
-       EXT4_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
-#define EXT4_CLEAR_RO_COMPAT_FEATURE(sb,mask)                  \
-       EXT4_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
-#define EXT4_CLEAR_INCOMPAT_FEATURE(sb,mask)                   \
-       EXT4_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
-
 #define EXT4_FEATURE_COMPAT_DIR_PREALLOC       0x0001
 #define EXT4_FEATURE_COMPAT_IMAGIC_INODES      0x0002
 #define EXT4_FEATURE_COMPAT_HAS_JOURNAL                0x0004
index d7ccb7f..c930a01 100644 (file)
@@ -4679,6 +4679,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
        unsigned int credits;
        loff_t epos;
 
+       BUG_ON(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS));
        map.m_lblk = offset;
        map.m_len = len;
        /*
@@ -4693,13 +4694,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
         * credits to insert 1 extent into extent tree
         */
        credits = ext4_chunk_trans_blocks(inode, len);
-       /*
-        * We can only call ext_depth() on extent based inodes
-        */
-       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
-               depth = ext_depth(inode);
-       else
-               depth = -1;
+       depth = ext_depth(inode);
 
 retry:
        while (ret >= 0 && len) {
@@ -4966,13 +4961,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 
        trace_ext4_fallocate_enter(inode, offset, len, mode);
        lblk = offset >> blkbits;
-       /*
-        * We can't just convert len to max_blocks because
-        * If blocksize = 4096 offset = 3072 and len = 2048
-        */
-       max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
-               - lblk;
 
+       max_blocks = EXT4_MAX_BLOCKS(len, offset, blkbits);
        flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT;
        if (mode & FALLOC_FL_KEEP_SIZE)
                flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
@@ -5035,12 +5025,8 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
        unsigned int credits, blkbits = inode->i_blkbits;
 
        map.m_lblk = offset >> blkbits;
-       /*
-        * We can't just convert len to max_blocks because
-        * If blocksize = 4096 offset = 3072 and len = 2048
-        */
-       max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) -
-                     map.m_lblk);
+       max_blocks = EXT4_MAX_BLOCKS(len, offset, blkbits);
+
        /*
         * This is somewhat ugly but the idea is clear: When transaction is
         * reserved, everything goes into it. Otherwise we rather start several
@@ -5734,6 +5720,9 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
                        up_write(&EXT4_I(inode)->i_data_sem);
                        goto out_stop;
                }
+       } else {
+               ext4_ext_drop_refs(path);
+               kfree(path);
        }
 
        ret = ext4_es_remove_extent(inode, offset_lblk,
index 261ac37..25f763f 100644 (file)
@@ -91,9 +91,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos)
 static ssize_t
 ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
-       struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(iocb->ki_filp);
-       struct blk_plug plug;
        int o_direct = iocb->ki_flags & IOCB_DIRECT;
        int unaligned_aio = 0;
        int overwrite = 0;
@@ -134,18 +132,16 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (o_direct) {
                size_t length = iov_iter_count(from);
                loff_t pos = iocb->ki_pos;
-               blk_start_plug(&plug);
 
                /* check whether we do a DIO overwrite or not */
                if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
-                   !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
+                   pos + length <= i_size_read(inode)) {
                        struct ext4_map_blocks map;
                        unsigned int blkbits = inode->i_blkbits;
                        int err, len;
 
                        map.m_lblk = pos >> blkbits;
-                       map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
-                               - map.m_lblk;
+                       map.m_len = EXT4_MAX_BLOCKS(length, pos, blkbits);
                        len = map.m_len;
 
                        err = ext4_map_blocks(NULL, inode, &map, 0);
@@ -171,8 +167,6 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
        if (ret > 0)
                ret = generic_write_sync(iocb, ret);
-       if (o_direct)
-               blk_finish_plug(&plug);
 
        return ret;
 
index 5c43725..88effb1 100644 (file)
@@ -61,6 +61,13 @@ static int ext4_sync_parent(struct inode *inode)
                        break;
                iput(inode);
                inode = next;
+               /*
+                * The directory inode may have gone through rmdir by now. But
+                * the inode itself and its blocks are still allocated (we hold
+                * a reference to the inode so it didn't go through
+                * ext4_evict_inode()) and so we are safe to flush metadata
+                * blocks and the inode.
+                */
                ret = sync_mapping_buffers(inode->i_mapping);
                if (ret)
                        break;
@@ -107,7 +114,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        if (!journal) {
                ret = __generic_file_fsync(file, start, end, datasync);
-               if (!ret && !hlist_empty(&inode->i_dentry))
+               if (!ret)
                        ret = ext4_sync_parent(inode);
                if (test_opt(inode->i_sb, BARRIER))
                        goto issue_flush;
index 9e66cd1..170421e 100644 (file)
@@ -802,7 +802,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
        } else
                inode_init_owner(inode, dir, mode);
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT) &&
+       if (ext4_has_feature_project(sb) &&
            ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT))
                ei->i_projid = EXT4_I(dir)->i_projid;
        else
index c6ea25a..cd91882 100644 (file)
@@ -647,11 +647,19 @@ found:
                /*
                 * We have to zeroout blocks before inserting them into extent
                 * status tree. Otherwise someone could look them up there and
-                * use them before they are really zeroed.
+                * use them before they are really zeroed. We also have to
+                * unmap metadata before zeroing as otherwise writeback can
+                * overwrite zeros with stale data from block device.
                 */
                if (flags & EXT4_GET_BLOCKS_ZERO &&
                    map->m_flags & EXT4_MAP_MAPPED &&
                    map->m_flags & EXT4_MAP_NEW) {
+                       ext4_lblk_t i;
+
+                       for (i = 0; i < map->m_len; i++) {
+                               unmap_underlying_metadata(inode->i_sb->s_bdev,
+                                                         map->m_pblk + i);
+                       }
                        ret = ext4_issue_zeroout(inode, map->m_lblk,
                                                 map->m_pblk, map->m_len);
                        if (ret) {
@@ -1649,6 +1657,8 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd,
                        BUG_ON(!PageLocked(page));
                        BUG_ON(PageWriteback(page));
                        if (invalidate) {
+                               if (page_mapped(page))
+                                       clear_page_dirty_for_io(page);
                                block_invalidatepage(page, 0, PAGE_SIZE);
                                ClearPageUptodate(page);
                        }
@@ -3526,35 +3536,31 @@ out:
 
 static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter)
 {
-       int unlocked = 0;
-       struct inode *inode = iocb->ki_filp->f_mapping->host;
+       struct address_space *mapping = iocb->ki_filp->f_mapping;
+       struct inode *inode = mapping->host;
        ssize_t ret;
 
-       if (ext4_should_dioread_nolock(inode)) {
-               /*
-                * Nolock dioread optimization may be dynamically disabled
-                * via ext4_inode_block_unlocked_dio(). Check inode's state
-                * while holding extra i_dio_count ref.
-                */
-               inode_dio_begin(inode);
-               smp_mb();
-               if (unlikely(ext4_test_inode_state(inode,
-                                                   EXT4_STATE_DIOREAD_LOCK)))
-                       inode_dio_end(inode);
-               else
-                       unlocked = 1;
-       }
+       /*
+        * Shared inode_lock is enough for us - it protects against concurrent
+        * writes & truncates and since we take care of writing back page cache,
+        * we are protected against page writeback as well.
+        */
+       inode_lock_shared(inode);
        if (IS_DAX(inode)) {
-               ret = dax_do_io(iocb, inode, iter, ext4_dio_get_block,
-                               NULL, unlocked ? 0 : DIO_LOCKING);
+               ret = dax_do_io(iocb, inode, iter, ext4_dio_get_block, NULL, 0);
        } else {
+               size_t count = iov_iter_count(iter);
+
+               ret = filemap_write_and_wait_range(mapping, iocb->ki_pos,
+                                                  iocb->ki_pos + count);
+               if (ret)
+                       goto out_unlock;
                ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
                                           iter, ext4_dio_get_block,
-                                          NULL, NULL,
-                                          unlocked ? 0 : DIO_LOCKING);
+                                          NULL, NULL, 0);
        }
-       if (unlocked)
-               inode_dio_end(inode);
+out_unlock:
+       inode_unlock_shared(inode);
        return ret;
 }
 
@@ -3890,7 +3896,7 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
 }
 
 /*
- * ext4_punch_hole: punches a hole in a file by releaseing the blocks
+ * ext4_punch_hole: punches a hole in a file by releasing the blocks
  * associated with the given offset and length
  *
  * @inode:  File inode
@@ -3919,7 +3925,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
         * Write out all dirty pages to avoid race conditions
         * Then release them.
         */
-       if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+       if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
                ret = filemap_write_and_wait_range(mapping, offset,
                                                   offset + length - 1);
                if (ret)
@@ -4414,7 +4420,7 @@ static inline void ext4_iget_extra_inode(struct inode *inode,
 
 int ext4_get_projid(struct inode *inode, kprojid_t *projid)
 {
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, EXT4_FEATURE_RO_COMPAT_PROJECT))
+       if (!ext4_has_feature_project(inode->i_sb))
                return -EOPNOTSUPP;
        *projid = EXT4_I(inode)->i_projid;
        return 0;
@@ -4481,7 +4487,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
        inode->i_mode = le16_to_cpu(raw_inode->i_mode);
        i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
        i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT) &&
+       if (ext4_has_feature_project(sb) &&
            EXT4_INODE_SIZE(sb) > EXT4_GOOD_OLD_INODE_SIZE &&
            EXT4_FITS_IN_INODE(raw_inode, ei, i_projid))
                i_projid = (projid_t)le32_to_cpu(raw_inode->i_projid);
@@ -4814,14 +4820,14 @@ static int ext4_do_update_inode(handle_t *handle,
  * Fix up interoperability with old kernels. Otherwise, old inodes get
  * re-used with the upper 16 bits of the uid/gid intact
  */
-               if (!ei->i_dtime) {
+               if (ei->i_dtime && list_empty(&ei->i_orphan)) {
+                       raw_inode->i_uid_high = 0;
+                       raw_inode->i_gid_high = 0;
+               } else {
                        raw_inode->i_uid_high =
                                cpu_to_le16(high_16_bits(i_uid));
                        raw_inode->i_gid_high =
                                cpu_to_le16(high_16_bits(i_gid));
-               } else {
-                       raw_inode->i_uid_high = 0;
-                       raw_inode->i_gid_high = 0;
                }
        } else {
                raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(i_uid));
@@ -4885,8 +4891,7 @@ static int ext4_do_update_inode(handle_t *handle,
                }
        }
 
-       BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                       EXT4_FEATURE_RO_COMPAT_PROJECT) &&
+       BUG_ON(!ext4_has_feature_project(inode->i_sb) &&
               i_projid != EXT4_DEF_PROJID);
 
        if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
index 1bb7df5..bf5ae8e 100644 (file)
@@ -19,8 +19,6 @@
 #include "ext4_jbd2.h"
 #include "ext4.h"
 
-#define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1)
-
 /**
  * Swap memory between @a and @b for @len bytes.
  *
@@ -310,8 +308,7 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
        struct ext4_inode *raw_inode;
        struct dquot *transfer_to[MAXQUOTAS] = { };
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                       EXT4_FEATURE_RO_COMPAT_PROJECT)) {
+       if (!ext4_has_feature_project(sb)) {
                if (projid != EXT4_DEF_PROJID)
                        return -EOPNOTSUPP;
                else
@@ -772,6 +769,9 @@ resizefs_out:
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
                struct fscrypt_policy policy;
 
+               if (!ext4_has_feature_encrypt(sb))
+                       return -EOPNOTSUPP;
+
                if (copy_from_user(&policy,
                                   (struct fscrypt_policy __user *)arg,
                                   sizeof(policy)))
@@ -842,8 +842,7 @@ resizefs_out:
                ext4_get_inode_flags(ei);
                fa.fsx_xflags = ext4_iflags_to_xflags(ei->i_flags & EXT4_FL_USER_VISIBLE);
 
-               if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                               EXT4_FEATURE_RO_COMPAT_PROJECT)) {
+               if (ext4_has_feature_project(inode->i_sb)) {
                        fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
                                EXT4_I(inode)->i_projid);
                }
index a920c5d..6fc14de 100644 (file)
@@ -598,6 +598,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
                return -EOPNOTSUPP;
        }
 
+       if (ext4_encrypted_inode(orig_inode) ||
+           ext4_encrypted_inode(donor_inode)) {
+               ext4_msg(orig_inode->i_sb, KERN_ERR,
+                        "Online defrag not supported for encrypted files");
+               return -EOPNOTSUPP;
+       }
+
        /* Protect orig and donor inodes against a truncate */
        lock_two_nondirectories(orig_inode, donor_inode);
 
index 34c0142..c344b81 100644 (file)
@@ -639,7 +639,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                                        res = fscrypt_fname_alloc_buffer(
                                                dir, len,
                                                &fname_crypto_str);
-                                       if (res < 0)
+                                       if (res)
                                                printk(KERN_WARNING "Error "
                                                        "allocating crypto "
                                                        "buffer--skipping "
@@ -647,7 +647,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                                        res = fscrypt_fname_disk_to_usr(dir,
                                                0, 0, &de_name,
                                                &fname_crypto_str);
-                                       if (res < 0) {
+                                       if (res) {
                                                printk(KERN_WARNING "Error "
                                                        "converting filename "
                                                        "from disk to usr"
@@ -1011,7 +1011,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                        err = fscrypt_fname_disk_to_usr(dir, hinfo->hash,
                                        hinfo->minor_hash, &de_name,
                                        &fname_crypto_str);
-                       if (err < 0) {
+                       if (err) {
                                count = err;
                                goto errout;
                        }
@@ -2044,33 +2044,31 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
        frame->entries = entries;
        frame->at = entries;
        frame->bh = bh;
-       bh = bh2;
 
        retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
        if (retval)
                goto out_frames;        
-       retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
+       retval = ext4_handle_dirty_dirent_node(handle, dir, bh2);
        if (retval)
                goto out_frames;        
 
-       de = do_split(handle,dir, &bh, frame, &fname->hinfo);
+       de = do_split(handle,dir, &bh2, frame, &fname->hinfo);
        if (IS_ERR(de)) {
                retval = PTR_ERR(de);
                goto out_frames;
        }
-       dx_release(frames);
 
-       retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
-       brelse(bh);
-       return retval;
+       retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh2);
 out_frames:
        /*
         * Even if the block split failed, we have to properly write
         * out all the changes we did so far. Otherwise we can end up
         * with corrupted filesystem.
         */
-       ext4_mark_inode_dirty(handle, dir);
+       if (retval)
+               ext4_mark_inode_dirty(handle, dir);
        dx_release(frames);
+       brelse(bh2);
        return retval;
 }
 
@@ -3144,7 +3142,7 @@ static int ext4_symlink(struct inode *dir,
                istr.name = (const unsigned char *) symname;
                istr.len = len;
                err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
-               if (err < 0)
+               if (err)
                        goto err_drop_inode;
                sd->len = cpu_to_le16(ostr.len);
                disk_link.name = (char *) sd;
index a6132a7..b4cbee9 100644 (file)
@@ -405,14 +405,12 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
 {
        struct page *data_page = NULL;
        struct inode *inode = page->mapping->host;
-       unsigned block_start, blocksize;
+       unsigned block_start;
        struct buffer_head *bh, *head;
        int ret = 0;
        int nr_submitted = 0;
        int nr_to_submit = 0;
 
-       blocksize = 1 << inode->i_blkbits;
-
        BUG_ON(!PageLocked(page));
        BUG_ON(PageWriteback(page));
 
index 3ec8708..6db81fb 100644 (file)
@@ -78,6 +78,8 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly);
 static void ext4_destroy_lazyinit_thread(void);
 static void ext4_unregister_li_request(struct super_block *sb);
 static void ext4_clear_request_list(void);
+static struct inode *ext4_get_journal_inode(struct super_block *sb,
+                                           unsigned int journal_inum);
 
 /*
  * Lock ordering
@@ -1267,7 +1269,7 @@ enum {
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
-       Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_dax,
+       Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
        Opt_lazytime, Opt_nolazytime,
        Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
@@ -1327,6 +1329,7 @@ static const match_table_t tokens = {
        {Opt_noquota, "noquota"},
        {Opt_quota, "quota"},
        {Opt_usrquota, "usrquota"},
+       {Opt_prjquota, "prjquota"},
        {Opt_barrier, "barrier=%u"},
        {Opt_barrier, "barrier"},
        {Opt_nobarrier, "nobarrier"},
@@ -1546,8 +1549,11 @@ static const struct mount_opts {
                                                        MOPT_SET | MOPT_Q},
        {Opt_grpquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_GRPQUOTA,
                                                        MOPT_SET | MOPT_Q},
+       {Opt_prjquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_PRJQUOTA,
+                                                       MOPT_SET | MOPT_Q},
        {Opt_noquota, (EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA |
-                      EXT4_MOUNT_GRPQUOTA), MOPT_CLEAR | MOPT_Q},
+                      EXT4_MOUNT_GRPQUOTA | EXT4_MOUNT_PRJQUOTA),
+                                                       MOPT_CLEAR | MOPT_Q},
        {Opt_usrjquota, 0, MOPT_Q},
        {Opt_grpjquota, 0, MOPT_Q},
        {Opt_offusrjquota, 0, MOPT_Q},
@@ -1836,13 +1842,17 @@ static int parse_options(char *options, struct super_block *sb,
                        return 0;
        }
 #ifdef CONFIG_QUOTA
-       if (ext4_has_feature_quota(sb) &&
-           (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) {
-               ext4_msg(sb, KERN_INFO, "Quota feature enabled, usrquota and grpquota "
-                        "mount options ignored.");
-               clear_opt(sb, USRQUOTA);
-               clear_opt(sb, GRPQUOTA);
-       } else if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
+       /*
+        * We do the test below only for project quotas. 'usrquota' and
+        * 'grpquota' mount options are allowed even without quota feature
+        * to support legacy quotas in quota files.
+        */
+       if (test_opt(sb, PRJQUOTA) && !ext4_has_feature_project(sb)) {
+               ext4_msg(sb, KERN_ERR, "Project quota feature not enabled. "
+                        "Cannot enable project quota enforcement.");
+               return 0;
+       }
+       if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
                if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
                        clear_opt(sb, USRQUOTA);
 
@@ -2741,7 +2751,6 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
        sb = elr->lr_super;
        ngroups = EXT4_SB(sb)->s_groups_count;
 
-       sb_start_write(sb);
        for (group = elr->lr_next_group; group < ngroups; group++) {
                gdp = ext4_get_group_desc(sb, group, NULL);
                if (!gdp) {
@@ -2768,8 +2777,6 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
                elr->lr_next_sched = jiffies + elr->lr_timeout;
                elr->lr_next_group = group + 1;
        }
-       sb_end_write(sb);
-
        return ret;
 }
 
@@ -2834,19 +2841,43 @@ cont_thread:
                        mutex_unlock(&eli->li_list_mtx);
                        goto exit_thread;
                }
-
                list_for_each_safe(pos, n, &eli->li_request_list) {
+                       int err = 0;
+                       int progress = 0;
                        elr = list_entry(pos, struct ext4_li_request,
                                         lr_request);
 
-                       if (time_after_eq(jiffies, elr->lr_next_sched)) {
-                               if (ext4_run_li_request(elr) != 0) {
-                                       /* error, remove the lazy_init job */
-                                       ext4_remove_li_request(elr);
-                                       continue;
+                       if (time_before(jiffies, elr->lr_next_sched)) {
+                               if (time_before(elr->lr_next_sched, next_wakeup))
+                                       next_wakeup = elr->lr_next_sched;
+                               continue;
+                       }
+                       if (down_read_trylock(&elr->lr_super->s_umount)) {
+                               if (sb_start_write_trylock(elr->lr_super)) {
+                                       progress = 1;
+                                       /*
+                                        * We hold sb->s_umount, sb can not
+                                        * be removed from the list, it is
+                                        * now safe to drop li_list_mtx
+                                        */
+                                       mutex_unlock(&eli->li_list_mtx);
+                                       err = ext4_run_li_request(elr);
+                                       sb_end_write(elr->lr_super);
+                                       mutex_lock(&eli->li_list_mtx);
+                                       n = pos->next;
                                }
+                               up_read((&elr->lr_super->s_umount));
+                       }
+                       /* error, remove the lazy_init job */
+                       if (err) {
+                               ext4_remove_li_request(elr);
+                               continue;
+                       }
+                       if (!progress) {
+                               elr->lr_next_sched = jiffies +
+                                       (prandom_u32()
+                                        % (EXT4_DEF_LI_MAX_START_DELAY * HZ));
                        }
-
                        if (time_before(elr->lr_next_sched, next_wakeup))
                                next_wakeup = elr->lr_next_sched;
                }
@@ -3179,6 +3210,8 @@ int ext4_calculate_overhead(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
+       struct inode *j_inode;
+       unsigned int j_blocks, j_inum = le32_to_cpu(es->s_journal_inum);
        ext4_group_t i, ngroups = ext4_get_groups_count(sb);
        ext4_fsblk_t overhead = 0;
        char *buf = (char *) get_zeroed_page(GFP_NOFS);
@@ -3209,10 +3242,23 @@ int ext4_calculate_overhead(struct super_block *sb)
                        memset(buf, 0, PAGE_SIZE);
                cond_resched();
        }
-       /* Add the internal journal blocks as well */
+
+       /*
+        * Add the internal journal blocks whether the journal has been
+        * loaded or not
+        */
        if (sbi->s_journal && !sbi->journal_bdev)
                overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen);
-
+       else if (ext4_has_feature_journal(sb) && !sbi->s_journal) {
+               j_inode = ext4_get_journal_inode(sb, j_inum);
+               if (j_inode) {
+                       j_blocks = j_inode->i_size >> sb->s_blocksize_bits;
+                       overhead += EXT4_NUM_B2C(sbi, j_blocks);
+                       iput(j_inode);
+               } else {
+                       ext4_msg(sb, KERN_ERR, "can't get journal size");
+               }
+       }
        sbi->s_overhead = overhead;
        smp_wmb();
        free_page((unsigned long) buf);
@@ -4208,18 +4254,16 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
        write_unlock(&journal->j_state_lock);
 }
 
-static journal_t *ext4_get_journal(struct super_block *sb,
-                                  unsigned int journal_inum)
+static struct inode *ext4_get_journal_inode(struct super_block *sb,
+                                            unsigned int journal_inum)
 {
        struct inode *journal_inode;
-       journal_t *journal;
-
-       BUG_ON(!ext4_has_feature_journal(sb));
-
-       /* First, test for the existence of a valid inode on disk.  Bad
-        * things happen if we iget() an unused inode, as the subsequent
-        * iput() will try to delete it. */
 
+       /*
+        * Test for the existence of a valid inode on disk.  Bad things
+        * happen if we iget() an unused inode, as the subsequent iput()
+        * will try to delete it.
+        */
        journal_inode = ext4_iget(sb, journal_inum);
        if (IS_ERR(journal_inode)) {
                ext4_msg(sb, KERN_ERR, "no journal found");
@@ -4239,6 +4283,20 @@ static journal_t *ext4_get_journal(struct super_block *sb,
                iput(journal_inode);
                return NULL;
        }
+       return journal_inode;
+}
+
+static journal_t *ext4_get_journal(struct super_block *sb,
+                                  unsigned int journal_inum)
+{
+       struct inode *journal_inode;
+       journal_t *journal;
+
+       BUG_ON(!ext4_has_feature_journal(sb));
+
+       journal_inode = ext4_get_journal_inode(sb, journal_inum);
+       if (!journal_inode)
+               return NULL;
 
        journal = jbd2_journal_init_inode(journal_inode);
        if (!journal) {
@@ -5250,12 +5308,18 @@ static int ext4_enable_quotas(struct super_block *sb)
                le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
                le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
        };
+       bool quota_mopt[EXT4_MAXQUOTAS] = {
+               test_opt(sb, USRQUOTA),
+               test_opt(sb, GRPQUOTA),
+               test_opt(sb, PRJQUOTA),
+       };
 
        sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
        for (type = 0; type < EXT4_MAXQUOTAS; type++) {
                if (qf_inums[type]) {
                        err = ext4_quota_enable(sb, type, QFMT_VFS_V1,
-                                               DQUOT_USAGE_ENABLED);
+                               DQUOT_USAGE_ENABLED |
+                               (quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0));
                        if (err) {
                                ext4_warning(sb,
                                        "Failed to enable quota tracking "
index 4d83d9e..fdf1c61 100644 (file)
@@ -30,7 +30,6 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
        char *caddr, *paddr = NULL;
        struct fscrypt_str cstr, pstr;
        struct fscrypt_symlink_data *sd;
-       loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
        int res;
        u32 max_size = inode->i_sb->s_blocksize;
 
@@ -49,7 +48,6 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
                if (IS_ERR(cpage))
                        return ERR_CAST(cpage);
                caddr = page_address(cpage);
-               caddr[size] = 0;
        }
 
        /* Symlink is encrypted */
@@ -65,16 +63,14 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
        res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
        if (res)
                goto errout;
+       paddr = pstr.name;
 
        res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
-       if (res < 0)
+       if (res)
                goto errout;
 
-       paddr = pstr.name;
-
        /* Null-terminate the name */
-       if (res <= pstr.len)
-               paddr[res] = '\0';
+       paddr[pstr.len] = '\0';
        if (cpage)
                put_page(cpage);
        set_delayed_call(done, kfree_link, paddr);
index 2eb935c..c15d633 100644 (file)
@@ -199,6 +199,8 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
        }
 
        while (!IS_LAST_ENTRY(entry)) {
+               if (entry->e_value_block != 0)
+                       return -EFSCORRUPTED;
                if (entry->e_value_size != 0 &&
                    (value_start + le16_to_cpu(entry->e_value_offs) <
                     (void *)e + sizeof(__u32) ||
@@ -641,7 +643,7 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last,
                                    size_t *min_offs, void *base, int *total)
 {
        for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
-               if (!last->e_value_block && last->e_value_size) {
+               if (last->e_value_size) {
                        size_t offs = le16_to_cpu(last->e_value_offs);
                        if (offs < *min_offs)
                                *min_offs = offs;
@@ -661,7 +663,7 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
        /* Compute min_offs and last. */
        last = s->first;
        for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
-               if (!last->e_value_block && last->e_value_size) {
+               if (last->e_value_size) {
                        size_t offs = le16_to_cpu(last->e_value_offs);
                        if (offs < min_offs)
                                min_offs = offs;
@@ -669,7 +671,7 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
        }
        free = min_offs - ((void *)last - s->base) - sizeof(__u32);
        if (!s->not_found) {
-               if (!s->here->e_value_block && s->here->e_value_size) {
+               if (s->here->e_value_size) {
                        size_t size = le32_to_cpu(s->here->e_value_size);
                        free += EXT4_XATTR_SIZE(size);
                }
@@ -691,7 +693,7 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
                s->here->e_name_len = name_len;
                memcpy(s->here->e_name, i->name, name_len);
        } else {
-               if (!s->here->e_value_block && s->here->e_value_size) {
+               if (s->here->e_value_size) {
                        void *first_val = s->base + min_offs;
                        size_t offs = le16_to_cpu(s->here->e_value_offs);
                        void *val = s->base + offs;
@@ -725,8 +727,7 @@ ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s)
                        last = s->first;
                        while (!IS_LAST_ENTRY(last)) {
                                size_t o = le16_to_cpu(last->e_value_offs);
-                               if (!last->e_value_block &&
-                                   last->e_value_size && o < offs)
+                               if (last->e_value_size && o < offs)
                                        last->e_value_offs =
                                                cpu_to_le16(o + size);
                                last = EXT4_XATTR_NEXT(last);
@@ -1318,18 +1319,19 @@ retry:
  */
 static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
                                     int value_offs_shift, void *to,
-                                    void *from, size_t n, int blocksize)
+                                    void *from, size_t n)
 {
        struct ext4_xattr_entry *last = entry;
        int new_offs;
 
+       /* We always shift xattr headers further thus offsets get lower */
+       BUG_ON(value_offs_shift > 0);
+
        /* Adjust the value offsets of the entries */
        for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
-               if (!last->e_value_block && last->e_value_size) {
+               if (last->e_value_size) {
                        new_offs = le16_to_cpu(last->e_value_offs) +
                                                        value_offs_shift;
-                       BUG_ON(new_offs + le32_to_cpu(last->e_value_size)
-                                > blocksize);
                        last->e_value_offs = cpu_to_le16(new_offs);
                }
        }
@@ -1337,6 +1339,141 @@ static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
        memmove(to, from, n);
 }
 
+/*
+ * Move xattr pointed to by 'entry' from inode into external xattr block
+ */
+static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
+                                   struct ext4_inode *raw_inode,
+                                   struct ext4_xattr_entry *entry)
+{
+       struct ext4_xattr_ibody_find *is = NULL;
+       struct ext4_xattr_block_find *bs = NULL;
+       char *buffer = NULL, *b_entry_name = NULL;
+       size_t value_offs, value_size;
+       struct ext4_xattr_info i = {
+               .value = NULL,
+               .value_len = 0,
+               .name_index = entry->e_name_index,
+       };
+       struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
+       int error;
+
+       value_offs = le16_to_cpu(entry->e_value_offs);
+       value_size = le32_to_cpu(entry->e_value_size);
+
+       is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
+       bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
+       buffer = kmalloc(value_size, GFP_NOFS);
+       b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
+       if (!is || !bs || !buffer || !b_entry_name) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       is->s.not_found = -ENODATA;
+       bs->s.not_found = -ENODATA;
+       is->iloc.bh = NULL;
+       bs->bh = NULL;
+
+       /* Save the entry name and the entry value */
+       memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
+       memcpy(b_entry_name, entry->e_name, entry->e_name_len);
+       b_entry_name[entry->e_name_len] = '\0';
+       i.name = b_entry_name;
+
+       error = ext4_get_inode_loc(inode, &is->iloc);
+       if (error)
+               goto out;
+
+       error = ext4_xattr_ibody_find(inode, &i, is);
+       if (error)
+               goto out;
+
+       /* Remove the chosen entry from the inode */
+       error = ext4_xattr_ibody_set(handle, inode, &i, is);
+       if (error)
+               goto out;
+
+       i.name = b_entry_name;
+       i.value = buffer;
+       i.value_len = value_size;
+       error = ext4_xattr_block_find(inode, &i, bs);
+       if (error)
+               goto out;
+
+       /* Add entry which was removed from the inode into the block */
+       error = ext4_xattr_block_set(handle, inode, &i, bs);
+       if (error)
+               goto out;
+       error = 0;
+out:
+       kfree(b_entry_name);
+       kfree(buffer);
+       if (is)
+               brelse(is->iloc.bh);
+       kfree(is);
+       kfree(bs);
+
+       return error;
+}
+
+static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode,
+                                      struct ext4_inode *raw_inode,
+                                      int isize_diff, size_t ifree,
+                                      size_t bfree, int *total_ino)
+{
+       struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
+       struct ext4_xattr_entry *small_entry;
+       struct ext4_xattr_entry *entry;
+       struct ext4_xattr_entry *last;
+       unsigned int entry_size;        /* EA entry size */
+       unsigned int total_size;        /* EA entry size + value size */
+       unsigned int min_total_size;
+       int error;
+
+       while (isize_diff > ifree) {
+               entry = NULL;
+               small_entry = NULL;
+               min_total_size = ~0U;
+               last = IFIRST(header);
+               /* Find the entry best suited to be pushed into EA block */
+               for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
+                       total_size =
+                       EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) +
+                                       EXT4_XATTR_LEN(last->e_name_len);
+                       if (total_size <= bfree &&
+                           total_size < min_total_size) {
+                               if (total_size + ifree < isize_diff) {
+                                       small_entry = last;
+                               } else {
+                                       entry = last;
+                                       min_total_size = total_size;
+                               }
+                       }
+               }
+
+               if (entry == NULL) {
+                       if (small_entry == NULL)
+                               return -ENOSPC;
+                       entry = small_entry;
+               }
+
+               entry_size = EXT4_XATTR_LEN(entry->e_name_len);
+               total_size = entry_size +
+                       EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));
+               error = ext4_xattr_move_to_block(handle, inode, raw_inode,
+                                                entry);
+               if (error)
+                       return error;
+
+               *total_ino -= entry_size;
+               ifree += total_size;
+               bfree -= total_size;
+       }
+
+       return 0;
+}
+
 /*
  * Expand an inode by new_extra_isize bytes when EAs are present.
  * Returns 0 on success or negative error number on failure.
@@ -1345,14 +1482,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
                               struct ext4_inode *raw_inode, handle_t *handle)
 {
        struct ext4_xattr_ibody_header *header;
-       struct ext4_xattr_entry *entry, *last, *first;
        struct buffer_head *bh = NULL;
-       struct ext4_xattr_ibody_find *is = NULL;
-       struct ext4_xattr_block_find *bs = NULL;
-       char *buffer = NULL, *b_entry_name = NULL;
-       size_t min_offs, free;
+       size_t min_offs;
+       size_t ifree, bfree;
        int total_ino;
-       void *base, *start, *end;
+       void *base, *end;
        int error = 0, tried_min_extra_isize = 0;
        int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
        int isize_diff; /* How much do we need to grow i_extra_isize */
@@ -1368,34 +1502,24 @@ retry:
                goto out;
 
        header = IHDR(inode, raw_inode);
-       entry = IFIRST(header);
 
        /*
         * Check if enough free space is available in the inode to shift the
         * entries ahead by new_extra_isize.
         */
 
-       base = start = entry;
+       base = IFIRST(header);
        end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
        min_offs = end - base;
-       last = entry;
        total_ino = sizeof(struct ext4_xattr_ibody_header);
 
        error = xattr_check_inode(inode, header, end);
        if (error)
                goto cleanup;
 
-       free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
-       if (free >= isize_diff) {
-               entry = IFIRST(header);
-               ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize
-                               - new_extra_isize, (void *)raw_inode +
-                               EXT4_GOOD_OLD_INODE_SIZE + new_extra_isize,
-                               (void *)header, total_ino,
-                               inode->i_sb->s_blocksize);
-               EXT4_I(inode)->i_extra_isize = new_extra_isize;
-               goto out;
-       }
+       ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino);
+       if (ifree >= isize_diff)
+               goto shift;
 
        /*
         * Enough free space isn't available in the inode, check if
@@ -1413,146 +1537,44 @@ retry:
                        goto cleanup;
                }
                base = BHDR(bh);
-               first = BFIRST(bh);
                end = bh->b_data + bh->b_size;
                min_offs = end - base;
-               free = ext4_xattr_free_space(first, &min_offs, base, NULL);
-               if (free < isize_diff) {
+               bfree = ext4_xattr_free_space(BFIRST(bh), &min_offs, base,
+                                             NULL);
+               if (bfree + ifree < isize_diff) {
                        if (!tried_min_extra_isize && s_min_extra_isize) {
                                tried_min_extra_isize++;
                                new_extra_isize = s_min_extra_isize;
                                brelse(bh);
                                goto retry;
                        }
-                       error = -1;
+                       error = -ENOSPC;
                        goto cleanup;
                }
        } else {
-               free = inode->i_sb->s_blocksize;
+               bfree = inode->i_sb->s_blocksize;
        }
 
-       while (isize_diff > 0) {
-               size_t offs, size, entry_size;
-               struct ext4_xattr_entry *small_entry = NULL;
-               struct ext4_xattr_info i = {
-                       .value = NULL,
-                       .value_len = 0,
-               };
-               unsigned int total_size;  /* EA entry size + value size */
-               unsigned int shift_bytes; /* No. of bytes to shift EAs by? */
-               unsigned int min_total_size = ~0U;
-
-               is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
-               bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
-               if (!is || !bs) {
-                       error = -ENOMEM;
-                       goto cleanup;
-               }
-
-               is->s.not_found = -ENODATA;
-               bs->s.not_found = -ENODATA;
-               is->iloc.bh = NULL;
-               bs->bh = NULL;
-
-               last = IFIRST(header);
-               /* Find the entry best suited to be pushed into EA block */
-               entry = NULL;
-               for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
-                       total_size =
-                       EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) +
-                                       EXT4_XATTR_LEN(last->e_name_len);
-                       if (total_size <= free && total_size < min_total_size) {
-                               if (total_size < isize_diff) {
-                                       small_entry = last;
-                               } else {
-                                       entry = last;
-                                       min_total_size = total_size;
-                               }
-                       }
-               }
-
-               if (entry == NULL) {
-                       if (small_entry) {
-                               entry = small_entry;
-                       } else {
-                               if (!tried_min_extra_isize &&
-                                   s_min_extra_isize) {
-                                       tried_min_extra_isize++;
-                                       new_extra_isize = s_min_extra_isize;
-                                       kfree(is); is = NULL;
-                                       kfree(bs); bs = NULL;
-                                       brelse(bh);
-                                       goto retry;
-                               }
-                               error = -1;
-                               goto cleanup;
-                       }
-               }
-               offs = le16_to_cpu(entry->e_value_offs);
-               size = le32_to_cpu(entry->e_value_size);
-               entry_size = EXT4_XATTR_LEN(entry->e_name_len);
-               i.name_index = entry->e_name_index,
-               buffer = kmalloc(EXT4_XATTR_SIZE(size), GFP_NOFS);
-               b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
-               if (!buffer || !b_entry_name) {
-                       error = -ENOMEM;
-                       goto cleanup;
+       error = ext4_xattr_make_inode_space(handle, inode, raw_inode,
+                                           isize_diff, ifree, bfree,
+                                           &total_ino);
+       if (error) {
+               if (error == -ENOSPC && !tried_min_extra_isize &&
+                   s_min_extra_isize) {
+                       tried_min_extra_isize++;
+                       new_extra_isize = s_min_extra_isize;
+                       brelse(bh);
+                       goto retry;
                }
-               /* Save the entry name and the entry value */
-               memcpy(buffer, (void *)IFIRST(header) + offs,
-                      EXT4_XATTR_SIZE(size));
-               memcpy(b_entry_name, entry->e_name, entry->e_name_len);
-               b_entry_name[entry->e_name_len] = '\0';
-               i.name = b_entry_name;
-
-               error = ext4_get_inode_loc(inode, &is->iloc);
-               if (error)
-                       goto cleanup;
-
-               error = ext4_xattr_ibody_find(inode, &i, is);
-               if (error)
-                       goto cleanup;
-
-               /* Remove the chosen entry from the inode */
-               error = ext4_xattr_ibody_set(handle, inode, &i, is);
-               if (error)
-                       goto cleanup;
-               total_ino -= entry_size;
-
-               entry = IFIRST(header);
-               if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff)
-                       shift_bytes = isize_diff;
-               else
-                       shift_bytes = entry_size + EXT4_XATTR_SIZE(size);
-               /* Adjust the offsets and shift the remaining entries ahead */
-               ext4_xattr_shift_entries(entry, -shift_bytes,
-                       (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
-                       EXT4_I(inode)->i_extra_isize + shift_bytes,
-                       (void *)header, total_ino, inode->i_sb->s_blocksize);
-
-               isize_diff -= shift_bytes;
-               EXT4_I(inode)->i_extra_isize += shift_bytes;
-               header = IHDR(inode, raw_inode);
-
-               i.name = b_entry_name;
-               i.value = buffer;
-               i.value_len = size;
-               error = ext4_xattr_block_find(inode, &i, bs);
-               if (error)
-                       goto cleanup;
-
-               /* Add entry which was removed from the inode into the block */
-               error = ext4_xattr_block_set(handle, inode, &i, bs);
-               if (error)
-                       goto cleanup;
-               kfree(b_entry_name);
-               kfree(buffer);
-               b_entry_name = NULL;
-               buffer = NULL;
-               brelse(is->iloc.bh);
-               kfree(is);
-               kfree(bs);
+               goto cleanup;
        }
+shift:
+       /* Adjust the offsets and shift the remaining entries ahead */
+       ext4_xattr_shift_entries(IFIRST(header), EXT4_I(inode)->i_extra_isize
+                       - new_extra_isize, (void *)raw_inode +
+                       EXT4_GOOD_OLD_INODE_SIZE + new_extra_isize,
+                       (void *)header, total_ino);
+       EXT4_I(inode)->i_extra_isize = new_extra_isize;
        brelse(bh);
 out:
        ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
@@ -1560,12 +1582,6 @@ out:
        return 0;
 
 cleanup:
-       kfree(b_entry_name);
-       kfree(buffer);
-       if (is)
-               brelse(is->iloc.bh);
-       kfree(is);
-       kfree(bs);
        brelse(bh);
        /*
         * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
@@ -1734,7 +1750,7 @@ static inline void ext4_xattr_hash_entry(struct ext4_xattr_header *header,
                       *name++;
        }
 
-       if (entry->e_value_block == 0 && entry->e_value_size != 0) {
+       if (entry->e_value_size != 0) {
                __le32 *value = (__le32 *)((char *)header +
                        le16_to_cpu(entry->e_value_offs));
                for (n = (le32_to_cpu(entry->e_value_size) +
index cbf85f6..12b5836 100644 (file)
@@ -813,12 +813,12 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 
                if (f2fs_encrypted_inode(d->inode)) {
                        int save_len = fstr->len;
-                       int ret;
+                       int err;
 
-                       ret = fscrypt_fname_disk_to_usr(d->inode,
+                       err = fscrypt_fname_disk_to_usr(d->inode,
                                                (u32)de->hash_code, 0,
                                                &de_name, fstr);
-                       if (ret < 0)
+                       if (err)
                                return true;
 
                        de_name = *fstr;
index 300aef8..5625b87 100644 (file)
@@ -454,7 +454,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
                ostr.name = sd->encrypted_path;
                ostr.len = disk_link.len;
                err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
-               if (err < 0)
+               if (err)
                        goto err_out;
 
                sd->len = cpu_to_le16(ostr.len);
@@ -1051,7 +1051,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
                goto errout;
 
        res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
-       if (res < 0)
+       if (res)
                goto errout;
 
        /* this is broken symlink case */
@@ -1063,7 +1063,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
        paddr = pstr.name;
 
        /* Null-terminate the name */
-       paddr[res] = '\0';
+       paddr[pstr.len] = '\0';
 
        put_page(cpage);
        set_delayed_call(done, kfree_link, paddr);
index 46261a6..927da49 100644 (file)
@@ -1090,11 +1090,15 @@ static void jbd2_stats_proc_exit(journal_t *journal)
  * very few fields yet: that has to wait until we have created the
  * journal structures from from scratch, or loaded them from disk. */
 
-static journal_t * journal_init_common (void)
+static journal_t *journal_init_common(struct block_device *bdev,
+                       struct block_device *fs_dev,
+                       unsigned long long start, int len, int blocksize)
 {
        static struct lock_class_key jbd2_trans_commit_key;
        journal_t *journal;
        int err;
+       struct buffer_head *bh;
+       int n;
 
        journal = kzalloc(sizeof(*journal), GFP_KERNEL);
        if (!journal)
@@ -1131,6 +1135,32 @@ static journal_t * journal_init_common (void)
        lockdep_init_map(&journal->j_trans_commit_map, "jbd2_handle",
                         &jbd2_trans_commit_key, 0);
 
+       /* journal descriptor can store up to n blocks -bzzz */
+       journal->j_blocksize = blocksize;
+       journal->j_dev = bdev;
+       journal->j_fs_dev = fs_dev;
+       journal->j_blk_offset = start;
+       journal->j_maxlen = len;
+       n = journal->j_blocksize / sizeof(journal_block_tag_t);
+       journal->j_wbufsize = n;
+       journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
+                                       GFP_KERNEL);
+       if (!journal->j_wbuf) {
+               kfree(journal);
+               return NULL;
+       }
+
+       bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize);
+       if (!bh) {
+               pr_err("%s: Cannot get buffer for journal superblock\n",
+                       __func__);
+               kfree(journal->j_wbuf);
+               kfree(journal);
+               return NULL;
+       }
+       journal->j_sb_buffer = bh;
+       journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
        return journal;
 }
 
@@ -1157,51 +1187,21 @@ static journal_t * journal_init_common (void)
  *  range of blocks on an arbitrary block device.
  *
  */
-journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+journal_t *jbd2_journal_init_dev(struct block_device *bdev,
                        struct block_device *fs_dev,
                        unsigned long long start, int len, int blocksize)
 {
-       journal_t *journal = journal_init_common();
-       struct buffer_head *bh;
-       int n;
+       journal_t *journal;
 
+       journal = journal_init_common(bdev, fs_dev, start, len, blocksize);
        if (!journal)
                return NULL;
 
-       /* journal descriptor can store up to n blocks -bzzz */
-       journal->j_blocksize = blocksize;
-       journal->j_dev = bdev;
-       journal->j_fs_dev = fs_dev;
-       journal->j_blk_offset = start;
-       journal->j_maxlen = len;
        bdevname(journal->j_dev, journal->j_devname);
        strreplace(journal->j_devname, '/', '!');
        jbd2_stats_proc_init(journal);
-       n = journal->j_blocksize / sizeof(journal_block_tag_t);
-       journal->j_wbufsize = n;
-       journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
-       if (!journal->j_wbuf) {
-               printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n",
-                       __func__);
-               goto out_err;
-       }
-
-       bh = __getblk(journal->j_dev, start, journal->j_blocksize);
-       if (!bh) {
-               printk(KERN_ERR
-                      "%s: Cannot get buffer for journal superblock\n",
-                      __func__);
-               goto out_err;
-       }
-       journal->j_sb_buffer = bh;
-       journal->j_superblock = (journal_superblock_t *)bh->b_data;
 
        return journal;
-out_err:
-       kfree(journal->j_wbuf);
-       jbd2_stats_proc_exit(journal);
-       kfree(journal);
-       return NULL;
 }
 
 /**
@@ -1212,67 +1212,36 @@ out_err:
  * the journal.  The inode must exist already, must support bmap() and
  * must have all data blocks preallocated.
  */
-journal_t * jbd2_journal_init_inode (struct inode *inode)
+journal_t *jbd2_journal_init_inode(struct inode *inode)
 {
-       struct buffer_head *bh;
-       journal_t *journal = journal_init_common();
+       journal_t *journal;
        char *p;
-       int err;
-       int n;
        unsigned long long blocknr;
 
+       blocknr = bmap(inode, 0);
+       if (!blocknr) {
+               pr_err("%s: Cannot locate journal superblock\n",
+                       __func__);
+               return NULL;
+       }
+
+       jbd_debug(1, "JBD2: inode %s/%ld, size %lld, bits %d, blksize %ld\n",
+                 inode->i_sb->s_id, inode->i_ino, (long long) inode->i_size,
+                 inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
+
+       journal = journal_init_common(inode->i_sb->s_bdev, inode->i_sb->s_bdev,
+                       blocknr, inode->i_size >> inode->i_sb->s_blocksize_bits,
+                       inode->i_sb->s_blocksize);
        if (!journal)
                return NULL;
 
-       journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev;
        journal->j_inode = inode;
        bdevname(journal->j_dev, journal->j_devname);
        p = strreplace(journal->j_devname, '/', '!');
        sprintf(p, "-%lu", journal->j_inode->i_ino);
-       jbd_debug(1,
-                 "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
-                 journal, inode->i_sb->s_id, inode->i_ino,
-                 (long long) inode->i_size,
-                 inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
-
-       journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
-       journal->j_blocksize = inode->i_sb->s_blocksize;
        jbd2_stats_proc_init(journal);
 
-       /* journal descriptor can store up to n blocks -bzzz */
-       n = journal->j_blocksize / sizeof(journal_block_tag_t);
-       journal->j_wbufsize = n;
-       journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
-       if (!journal->j_wbuf) {
-               printk(KERN_ERR "%s: Can't allocate bhs for commit thread\n",
-                       __func__);
-               goto out_err;
-       }
-
-       err = jbd2_journal_bmap(journal, 0, &blocknr);
-       /* If that failed, give up */
-       if (err) {
-               printk(KERN_ERR "%s: Cannot locate journal superblock\n",
-                      __func__);
-               goto out_err;
-       }
-
-       bh = getblk_unmovable(journal->j_dev, blocknr, journal->j_blocksize);
-       if (!bh) {
-               printk(KERN_ERR
-                      "%s: Cannot get buffer for journal superblock\n",
-                      __func__);
-               goto out_err;
-       }
-       journal->j_sb_buffer = bh;
-       journal->j_superblock = (journal_superblock_t *)bh->b_data;
-
        return journal;
-out_err:
-       kfree(journal->j_wbuf);
-       jbd2_stats_proc_exit(journal);
-       kfree(journal);
-       return NULL;
 }
 
 /*
index b5bc3e2..3d8246a 100644 (file)
@@ -159,6 +159,7 @@ static void wait_transaction_locked(journal_t *journal)
        read_unlock(&journal->j_state_lock);
        if (need_to_start)
                jbd2_log_start_commit(journal, tid);
+       jbd2_might_wait_for_commit(journal);
        schedule();
        finish_wait(&journal->j_wait_transaction_locked, &wait);
 }
@@ -182,8 +183,6 @@ static int add_transaction_credits(journal_t *journal, int blocks,
        int needed;
        int total = blocks + rsv_blocks;
 
-       jbd2_might_wait_for_commit(journal);
-
        /*
         * If the current transaction is locked down for commit, wait
         * for the lock to be released.
@@ -214,6 +213,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
                if (atomic_read(&journal->j_reserved_credits) + total >
                    journal->j_max_transaction_buffers) {
                        read_unlock(&journal->j_state_lock);
+                       jbd2_might_wait_for_commit(journal);
                        wait_event(journal->j_wait_reserved,
                                   atomic_read(&journal->j_reserved_credits) + total <=
                                   journal->j_max_transaction_buffers);
@@ -238,6 +238,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
        if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) {
                atomic_sub(total, &t->t_outstanding_credits);
                read_unlock(&journal->j_state_lock);
+               jbd2_might_wait_for_commit(journal);
                write_lock(&journal->j_state_lock);
                if (jbd2_log_space_left(journal) < jbd2_space_needed(journal))
                        __jbd2_log_wait_for_space(journal);
@@ -255,6 +256,7 @@ static int add_transaction_credits(journal_t *journal, int blocks,
                sub_reserved_credits(journal, rsv_blocks);
                atomic_sub(total, &t->t_outstanding_credits);
                read_unlock(&journal->j_state_lock);
+               jbd2_might_wait_for_commit(journal);
                wait_event(journal->j_wait_reserved,
                         atomic_read(&journal->j_reserved_credits) + rsv_blocks
                         <= journal->j_max_transaction_buffers / 2);
index eccda3a..c5bd19f 100644 (file)
@@ -366,7 +366,11 @@ struct mb_cache *mb_cache_create(int bucket_bits)
        cache->c_shrink.count_objects = mb_cache_count;
        cache->c_shrink.scan_objects = mb_cache_scan;
        cache->c_shrink.seeks = DEFAULT_SEEKS;
-       register_shrinker(&cache->c_shrink);
+       if (register_shrinker(&cache->c_shrink)) {
+               kfree(cache->c_hash);
+               kfree(cache);
+               goto err_out;
+       }
 
        INIT_WORK(&cache->c_shrink_work, mb_cache_shrink_worker);
 
index e44b88b..225bdb7 100644 (file)
 #include <linux/cache.h>
 
 #ifdef CONFIG_SMP
-
-/*
- * We want a power-of-two.  Is there a better way than this?
- */
-
-#if NR_CPUS >= 32
-#define NR_BG_LOCKS    128
-#elif NR_CPUS >= 16
-#define NR_BG_LOCKS    64
-#elif NR_CPUS >= 8
-#define NR_BG_LOCKS    32
-#elif NR_CPUS >= 4
-#define NR_BG_LOCKS    16
-#elif NR_CPUS >= 2
-#define NR_BG_LOCKS    8
+#define NR_BG_LOCKS    (4 << ilog2(NR_CPUS < 32 ? NR_CPUS : 32))
 #else
-#define NR_BG_LOCKS    4
-#endif
-
-#else  /* CONFIG_SMP */
 #define NR_BG_LOCKS    1
-#endif /* CONFIG_SMP */
+#endif
 
 struct bgl_lock {
        spinlock_t lock;
@@ -49,14 +31,10 @@ static inline void bgl_lock_init(struct blockgroup_lock *bgl)
                spin_lock_init(&bgl->locks[i].lock);
 }
 
-/*
- * The accessor is a macro so we can embed a blockgroup_lock into different
- * superblock types
- */
 static inline spinlock_t *
 bgl_lock_ptr(struct blockgroup_lock *bgl, unsigned int block_group)
 {
-       return &bgl->locks[(block_group) & (NR_BG_LOCKS-1)].lock;
+       return &bgl->locks[block_group & (NR_BG_LOCKS-1)].lock;
 }
 
 #endif
index 76cff18..ff8b11b 100644 (file)
@@ -111,23 +111,6 @@ struct fscrypt_completion_result {
        struct fscrypt_completion_result ecr = { \
                COMPLETION_INITIALIZER((ecr).completion), 0 }
 
-static inline int fscrypt_key_size(int mode)
-{
-       switch (mode) {
-       case FS_ENCRYPTION_MODE_AES_256_XTS:
-               return FS_AES_256_XTS_KEY_SIZE;
-       case FS_ENCRYPTION_MODE_AES_256_GCM:
-               return FS_AES_256_GCM_KEY_SIZE;
-       case FS_ENCRYPTION_MODE_AES_256_CBC:
-               return FS_AES_256_CBC_KEY_SIZE;
-       case FS_ENCRYPTION_MODE_AES_256_CTS:
-               return FS_AES_256_CTS_KEY_SIZE;
-       default:
-               BUG();
-       }
-       return 0;
-}
-
 #define FS_FNAME_NUM_SCATTER_ENTRIES   4
 #define FS_CRYPTO_BLOCK_SIZE           16
 #define FS_FNAME_CRYPTO_DIGEST_SIZE    32
@@ -202,13 +185,6 @@ static inline bool fscrypt_valid_filenames_enc_mode(u32 mode)
        return (mode == FS_ENCRYPTION_MODE_AES_256_CTS);
 }
 
-static inline u32 fscrypt_validate_encryption_key_size(u32 mode, u32 size)
-{
-       if (size == fscrypt_key_size(mode))
-               return size;
-       return 0;
-}
-
 static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
 {
        if (str->len == 1 && str->name[0] == '.')