5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1) // SPDX-License-Identifier: GPL-2.0-or-later
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 2) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 3) * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 4) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 5)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 6) #include <linux/iversion.h>
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 7) #include <linux/namei.h>
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 8) #include <linux/slab.h>
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 9) #include <linux/buffer_head.h>
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 10) #include <linux/nls.h>
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 11)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 12) #include "exfat_raw.h"
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 13) #include "exfat_fs.h"
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 14)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 15) static inline unsigned long exfat_d_version(struct dentry *dentry)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 16) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 17) return (unsigned long) dentry->d_fsdata;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 18) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 19)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 20) static inline void exfat_d_version_set(struct dentry *dentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 21) unsigned long version)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 22) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 23) dentry->d_fsdata = (void *) version;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 24) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 25)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 26) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 27) * If new entry was created in the parent, it could create the 8.3 alias (the
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 28) * shortname of logname). So, the parent may have the negative-dentry which
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 29) * matches the created 8.3 alias.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 30) *
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 31) * If it happened, the negative dentry isn't actually negative anymore. So,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 32) * drop it.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 33) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 34) static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 35) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 36) int ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 37)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 38) if (flags & LOOKUP_RCU)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 39) return -ECHILD;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 40)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 41) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 42) * This is not negative dentry. Always valid.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 43) *
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 44) * Note, rename() to existing directory entry will have ->d_inode, and
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 45) * will use existing name which isn't specified name by user.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 46) *
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 47) * We may be able to drop this positive dentry here. But dropping
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 48) * positive dentry isn't good idea. So it's unsupported like
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 49) * rename("filename", "FILENAME") for now.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 50) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 51) if (d_really_is_positive(dentry))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 52) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 53)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 54) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 55) * Drop the negative dentry, in order to make sure to use the case
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 56) * sensitive name which is specified by user if this is for creation.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 57) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 58) if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 59) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 60)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 61) spin_lock(&dentry->d_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 62) ret = inode_eq_iversion(d_inode(dentry->d_parent),
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 63) exfat_d_version(dentry));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 64) spin_unlock(&dentry->d_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 65) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 66) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 67)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 68) /* returns the length of a struct qstr, ignoring trailing dots */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 69) static unsigned int exfat_striptail_len(unsigned int len, const char *name)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 70) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 71) while (len && name[len - 1] == '.')
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 72) len--;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 73) return len;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 74) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 75)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 76) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 77) * Compute the hash for the exfat name corresponding to the dentry. If the name
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 78) * is invalid, we leave the hash code unchanged so that the existing dentry can
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 79) * be used. The exfat fs routines will return ENOENT or EINVAL as appropriate.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 80) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 81) static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 82) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 83) struct super_block *sb = dentry->d_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 84) struct nls_table *t = EXFAT_SB(sb)->nls_io;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 85) const unsigned char *name = qstr->name;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 86) unsigned int len = exfat_striptail_len(qstr->len, qstr->name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 87) unsigned long hash = init_name_hash(dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 88) int i, charlen;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 89) wchar_t c;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 90)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 91) for (i = 0; i < len; i += charlen) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 92) charlen = t->char2uni(&name[i], len - i, &c);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 93) if (charlen < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 94) return charlen;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 95) hash = partial_name_hash(exfat_toupper(sb, c), hash);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 96) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 97)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 98) qstr->hash = end_name_hash(hash);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 99) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 100) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 101)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 102) static int exfat_d_cmp(const struct dentry *dentry, unsigned int len,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 103) const char *str, const struct qstr *name)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 104) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 105) struct super_block *sb = dentry->d_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 106) struct nls_table *t = EXFAT_SB(sb)->nls_io;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 107) unsigned int alen = exfat_striptail_len(name->len, name->name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 108) unsigned int blen = exfat_striptail_len(len, str);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 109) wchar_t c1, c2;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 110) int charlen, i;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 111)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 112) if (alen != blen)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 113) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 114)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 115) for (i = 0; i < len; i += charlen) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 116) charlen = t->char2uni(&name->name[i], alen - i, &c1);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 117) if (charlen < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 118) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 119) if (charlen != t->char2uni(&str[i], blen - i, &c2))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 120) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 121)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 122) if (exfat_toupper(sb, c1) != exfat_toupper(sb, c2))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 123) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 124) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 125)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 126) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 127) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 128)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 129) const struct dentry_operations exfat_dentry_ops = {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 130) .d_revalidate = exfat_d_revalidate,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 131) .d_hash = exfat_d_hash,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 132) .d_compare = exfat_d_cmp,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 133) };
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 134)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 135) static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 136) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 137) struct super_block *sb = dentry->d_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 138) const unsigned char *name = qstr->name;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 139) unsigned int len = exfat_striptail_len(qstr->len, qstr->name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 140) unsigned long hash = init_name_hash(dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 141) int i, charlen;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 142) unicode_t u;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 143)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 144) for (i = 0; i < len; i += charlen) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 145) charlen = utf8_to_utf32(&name[i], len - i, &u);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 146) if (charlen < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 147) return charlen;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 148)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 149) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 150) * exfat_toupper() works only for code points up to the U+FFFF.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 151) */
dddf7da3985ee (Pali Rohár 2020-03-17 23:25:52 +0100 152) hash = partial_name_hash(u <= 0xFFFF ? exfat_toupper(sb, u) : u,
dddf7da3985ee (Pali Rohár 2020-03-17 23:25:52 +0100 153) hash);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 154) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 155)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 156) qstr->hash = end_name_hash(hash);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 157) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 158) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 159)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 160) static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 161) const char *str, const struct qstr *name)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 162) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 163) struct super_block *sb = dentry->d_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 164) unsigned int alen = exfat_striptail_len(name->len, name->name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 165) unsigned int blen = exfat_striptail_len(len, str);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 166) unicode_t u_a, u_b;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 167) int charlen, i;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 168)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 169) if (alen != blen)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 170) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 171)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 172) for (i = 0; i < alen; i += charlen) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 173) charlen = utf8_to_utf32(&name->name[i], alen - i, &u_a);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 174) if (charlen < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 175) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 176) if (charlen != utf8_to_utf32(&str[i], blen - i, &u_b))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 177) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 178)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 179) if (u_a <= 0xFFFF && u_b <= 0xFFFF) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 180) if (exfat_toupper(sb, u_a) != exfat_toupper(sb, u_b))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 181) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 182) } else {
197298a64983e (Pali Rohár 2020-03-17 22:34:33 +0100 183) if (u_a != u_b)
197298a64983e (Pali Rohár 2020-03-17 22:34:33 +0100 184) return 1;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 185) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 186) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 187)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 188) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 189) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 190)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 191) const struct dentry_operations exfat_utf8_dentry_ops = {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 192) .d_revalidate = exfat_d_revalidate,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 193) .d_hash = exfat_utf8_d_hash,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 194) .d_compare = exfat_utf8_d_cmp,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 195) };
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 196)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 197) /* used only in search empty_slot() */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 198) #define CNT_UNUSED_NOHIT (-1)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 199) #define CNT_UNUSED_HIT (-2)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 200) /* search EMPTY CONTINUOUS "num_entries" entries */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 201) static int exfat_search_empty_slot(struct super_block *sb,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 202) struct exfat_hint_femp *hint_femp, struct exfat_chain *p_dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 203) int num_entries)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 204) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 205) int i, dentry, num_empty = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 206) int dentries_per_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 207) unsigned int type;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 208) struct exfat_chain clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 209) struct exfat_dentry *ep;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 210) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 211) struct buffer_head *bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 212)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 213) dentries_per_clu = sbi->dentries_per_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 214)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 215) if (hint_femp->eidx != EXFAT_HINT_NONE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 216) dentry = hint_femp->eidx;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 217) if (num_entries <= hint_femp->count) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 218) hint_femp->eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 219) return dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 220) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 221)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 222) exfat_chain_dup(&clu, &hint_femp->cur);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 223) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 224) exfat_chain_dup(&clu, p_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 225) dentry = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 226) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 227)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 228) while (clu.dir != EXFAT_EOF_CLUSTER) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 229) i = dentry & (dentries_per_clu - 1);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 230)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 231) for (; i < dentries_per_clu; i++, dentry++) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 232) ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 233) if (!ep)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 234) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 235) type = exfat_get_entry_type(ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 236) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 237)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 238) if (type == TYPE_UNUSED || type == TYPE_DELETED) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 239) num_empty++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 240) if (hint_femp->eidx == EXFAT_HINT_NONE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 241) hint_femp->eidx = dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 242) hint_femp->count = CNT_UNUSED_NOHIT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 243) exfat_chain_set(&hint_femp->cur,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 244) clu.dir, clu.size, clu.flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 245) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 246)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 247) if (type == TYPE_UNUSED &&
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 248) hint_femp->count != CNT_UNUSED_HIT)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 249) hint_femp->count = CNT_UNUSED_HIT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 250) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 251) if (hint_femp->eidx != EXFAT_HINT_NONE &&
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 252) hint_femp->count == CNT_UNUSED_HIT) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 253) /* unused empty group means
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 254) * an empty group which includes
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 255) * unused dentry
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 256) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 257) exfat_fs_error(sb,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 258) "found bogus dentry(%d) beyond unused empty group(%d) (start_clu : %u, cur_clu : %u)",
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 259) dentry, hint_femp->eidx,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 260) p_dir->dir, clu.dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 261) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 262) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 263)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 264) num_empty = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 265) hint_femp->eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 266) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 267)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 268) if (num_empty >= num_entries) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 269) /* found and invalidate hint_femp */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 270) hint_femp->eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 271) return (dentry - (num_entries - 1));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 272) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 273) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 274)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 275) if (clu.flags == ALLOC_NO_FAT_CHAIN) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 276) if (--clu.size > 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 277) clu.dir++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 278) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 279) clu.dir = EXFAT_EOF_CLUSTER;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 280) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 281) if (exfat_get_next_cluster(sb, &clu.dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 282) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 283) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 284) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 285)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 286) return -ENOSPC;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 287) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 288)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 289) static int exfat_check_max_dentries(struct inode *inode)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 290) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 291) if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 292) /*
9e456aeaacb6b (Namjae Jeon 2020-08-14 11:03:46 +0900 293) * exFAT spec allows a dir to grow up to 8388608(256MB)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 294) * dentries
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 295) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 296) return -ENOSPC;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 297) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 298) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 299) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 300)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 301) /* find empty directory entry.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 302) * if there isn't any empty slot, expand cluster chain.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 303) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 304) static int exfat_find_empty_entry(struct inode *inode,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 305) struct exfat_chain *p_dir, int num_entries)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 306) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 307) int dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 308) unsigned int ret, last_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 309) sector_t sector;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 310) loff_t size = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 311) struct exfat_chain clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 312) struct exfat_dentry *ep = NULL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 313) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 314) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 315) struct exfat_inode_info *ei = EXFAT_I(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 316) struct exfat_hint_femp hint_femp;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 317)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 318) hint_femp.eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 319)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 320) if (ei->hint_femp.eidx != EXFAT_HINT_NONE) {
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 321) hint_femp = ei->hint_femp;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 322) ei->hint_femp.eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 323) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 324)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 325) while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 326) num_entries)) < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 327) if (dentry == -EIO)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 328) break;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 329)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 330) if (exfat_check_max_dentries(inode))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 331) return -ENOSPC;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 332)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 333) /* we trust p_dir->size regardless of FAT type */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 334) if (exfat_find_last_cluster(sb, p_dir, &last_clu))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 335) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 336)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 337) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 338) * Allocate new cluster to this directory
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 339) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 340) exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 341)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 342) /* allocate a cluster */
23befe490ba88 (Hyeongseok Kim 2021-03-15 13:12:55 +0900 343) ret = exfat_alloc_cluster(inode, 1, &clu, IS_DIRSYNC(inode));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 344) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 345) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 346)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 347) if (exfat_zeroed_cluster(inode, clu.dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 348) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 349)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 350) /* append to the FAT chain */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 351) if (clu.flags != p_dir->flags) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 352) /* no-fat-chain bit is disabled,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 353) * so fat-chain should be synced with alloc-bitmap
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 354) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 355) exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 356) p_dir->flags = ALLOC_FAT_CHAIN;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 357) hint_femp.cur.flags = ALLOC_FAT_CHAIN;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 358) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 359)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 360) if (clu.flags == ALLOC_FAT_CHAIN)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 361) if (exfat_ent_set(sb, last_clu, clu.dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 362) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 363)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 364) if (hint_femp.eidx == EXFAT_HINT_NONE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 365) /* the special case that new dentry
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 366) * should be allocated from the start of new cluster
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 367) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 368) hint_femp.eidx = EXFAT_B_TO_DEN_IDX(p_dir->size, sbi);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 369) hint_femp.count = sbi->dentries_per_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 370)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 371) exfat_chain_set(&hint_femp.cur, clu.dir, 0, clu.flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 372) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 373) hint_femp.cur.size++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 374) p_dir->size++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 375) size = EXFAT_CLU_TO_B(p_dir->size, sbi);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 376)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 377) /* update the directory entry */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 378) if (p_dir->dir != sbi->root_dir) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 379) struct buffer_head *bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 380)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 381) ep = exfat_get_dentry(sb,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 382) &(ei->dir), ei->entry + 1, &bh, §or);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 383) if (!ep)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 384) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 385)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 386) ep->dentry.stream.valid_size = cpu_to_le64(size);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 387) ep->dentry.stream.size = ep->dentry.stream.valid_size;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 388) ep->dentry.stream.flags = p_dir->flags;
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 389) exfat_update_bh(bh, IS_DIRSYNC(inode));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 390) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 391) if (exfat_update_dir_chksum(inode, &(ei->dir),
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 392) ei->entry))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 393) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 394) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 395)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 396) /* directory inode should be updated in here */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 397) i_size_write(inode, size);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 398) EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 399) EXFAT_I(inode)->i_size_aligned += sbi->cluster_size;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 400) EXFAT_I(inode)->flags = p_dir->flags;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 401) inode->i_blocks += 1 << sbi->sect_per_clus_bits;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 402) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 403)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 404) return dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 405) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 406)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 407) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 408) * Name Resolution Functions :
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 409) * Zero if it was successful; otherwise nonzero.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 410) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 411) static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 412) struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 413) int lookup)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 414) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 415) int namelen;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 416) int lossy = NLS_NAME_NO_LOSSY;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 417) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 418) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 419) struct exfat_inode_info *ei = EXFAT_I(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 420)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 421) /* strip all trailing periods */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 422) namelen = exfat_striptail_len(strlen(path), path);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 423) if (!namelen)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 424) return -ENOENT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 425)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 426) if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 427) return -ENAMETOOLONG;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 428)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 429) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 430) * strip all leading spaces :
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 431) * "MS windows 7" supports leading spaces.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 432) * So we should skip this preprocessing for compatibility.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 433) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 434)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 435) /* file name conversion :
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 436) * If lookup case, we allow bad-name for compatibility.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 437) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 438) namelen = exfat_nls_to_utf16(sb, path, namelen, p_uniname,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 439) &lossy);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 440) if (namelen < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 441) return namelen; /* return error value */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 442)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 443) if ((lossy && !lookup) || !namelen)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 444) return -EINVAL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 445)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 446) exfat_chain_set(p_dir, ei->start_clu,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 447) EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 448)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 449) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 450) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 451)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 452) static inline int exfat_resolve_path(struct inode *inode,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 453) const unsigned char *path, struct exfat_chain *dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 454) struct exfat_uni_name *uni)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 455) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 456) return __exfat_resolve_path(inode, path, dir, uni, 0);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 457) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 458)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 459) static inline int exfat_resolve_path_for_lookup(struct inode *inode,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 460) const unsigned char *path, struct exfat_chain *dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 461) struct exfat_uni_name *uni)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 462) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 463) return __exfat_resolve_path(inode, path, dir, uni, 1);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 464) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 465)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 466) static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 467) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 468) return ((loff_t) info->dir.dir << 32) | (info->entry & 0xffffffff);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 469) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 470)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 471) static int exfat_add_entry(struct inode *inode, const char *path,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 472) struct exfat_chain *p_dir, unsigned int type,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 473) struct exfat_dir_entry *info)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 474) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 475) int ret, dentry, num_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 476) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 477) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 478) struct exfat_uni_name uniname;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 479) struct exfat_chain clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 480) int clu_size = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 481) unsigned int start_clu = EXFAT_FREE_CLUSTER;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 482)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 483) ret = exfat_resolve_path(inode, path, p_dir, &uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 484) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 485) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 486)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 487) num_entries = exfat_calc_num_entries(&uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 488) if (num_entries < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 489) ret = num_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 490) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 491) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 492)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 493) /* exfat_find_empty_entry must be called before alloc_cluster() */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 494) dentry = exfat_find_empty_entry(inode, p_dir, num_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 495) if (dentry < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 496) ret = dentry; /* -EIO or -ENOSPC */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 497) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 498) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 499)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 500) if (type == TYPE_DIR) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 501) ret = exfat_alloc_new_dir(inode, &clu);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 502) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 503) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 504) start_clu = clu.dir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 505) clu_size = sbi->cluster_size;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 506) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 507)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 508) /* update the directory entry */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 509) /* fill the dos name directory entry information of the created file.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 510) * the first cluster is not determined yet. (0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 511) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 512) ret = exfat_init_dir_entry(inode, p_dir, dentry, type,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 513) start_clu, clu_size);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 514) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 515) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 516)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 517) ret = exfat_init_ext_entry(inode, p_dir, dentry, num_entries, &uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 518) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 519) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 520)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 521) info->dir = *p_dir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 522) info->entry = dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 523) info->flags = ALLOC_NO_FAT_CHAIN;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 524) info->type = type;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 525)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 526) if (type == TYPE_FILE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 527) info->attr = ATTR_ARCHIVE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 528) info->start_clu = EXFAT_EOF_CLUSTER;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 529) info->size = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 530) info->num_subdirs = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 531) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 532) info->attr = ATTR_SUBDIR;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 533) info->start_clu = start_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 534) info->size = clu_size;
6c958a0955551 (Tetsuhiro Kohada 2020-09-11 13:44:39 +0900 535) info->num_subdirs = EXFAT_MIN_SUBDIR;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 536) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 537) memset(&info->crtime, 0, sizeof(info->crtime));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 538) memset(&info->mtime, 0, sizeof(info->mtime));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 539) memset(&info->atime, 0, sizeof(info->atime));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 540) out:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 541) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 542) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 543)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 544) static int exfat_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 545) struct dentry *dentry, umode_t mode, bool excl)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 546) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 547) struct super_block *sb = dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 548) struct inode *inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 549) struct exfat_chain cdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 550) struct exfat_dir_entry info;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 551) loff_t i_pos;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 552) int err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 553)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 554) mutex_lock(&EXFAT_SB(sb)->s_lock);
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 555) exfat_set_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 556) err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 557) &info);
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 558) exfat_clear_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 559) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 560) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 561)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 562) inode_inc_iversion(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 563) dir->i_ctime = dir->i_mtime = current_time(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 564) if (IS_DIRSYNC(dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 565) exfat_sync_inode(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 566) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 567) mark_inode_dirty(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 568)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 569) i_pos = exfat_make_i_pos(&info);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 570) inode = exfat_build_inode(sb, &info, i_pos);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 571) err = PTR_ERR_OR_ZERO(inode);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 572) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 573) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 574)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 575) inode_inc_iversion(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 576) inode->i_mtime = inode->i_atime = inode->i_ctime =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 577) EXFAT_I(inode)->i_crtime = current_time(inode);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 578) exfat_truncate_atime(&inode->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 579) /* timestamp is already written, so mark_inode_dirty() is unneeded. */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 580)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 581) d_instantiate(dentry, inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 582) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 583) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 584) return err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 585) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 586)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 587) /* lookup a file */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 588) static int exfat_find(struct inode *dir, struct qstr *qname,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 589) struct exfat_dir_entry *info)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 590) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 591) int ret, dentry, num_entries, count;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 592) struct exfat_chain cdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 593) struct exfat_uni_name uni_name;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 594) struct super_block *sb = dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 595) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 596) struct exfat_inode_info *ei = EXFAT_I(dir);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 597) struct exfat_dentry *ep, *ep2;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 598) struct exfat_entry_set_cache *es;
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 599) /* for optimized dir & entry to prevent long traverse of cluster chain */
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 600) struct exfat_hint hint_opt;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 601)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 602) if (qname->len == 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 603) return -ENOENT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 604)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 605) /* check the validity of directory name in the given pathname */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 606) ret = exfat_resolve_path_for_lookup(dir, qname->name, &cdir, &uni_name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 607) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 608) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 609)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 610) num_entries = exfat_calc_num_entries(&uni_name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 611) if (num_entries < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 612) return num_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 613)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 614) /* check the validation of hint_stat and initialize it if required */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 615) if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 616) ei->hint_stat.clu = cdir.dir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 617) ei->hint_stat.eidx = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 618) ei->version = (inode_peek_iversion_raw(dir) & 0xffffffff);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 619) ei->hint_femp.eidx = EXFAT_HINT_NONE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 620) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 621)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 622) /* search the file name for directories */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 623) dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name,
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 624) num_entries, TYPE_ALL, &hint_opt);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 625)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 626) if (dentry < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 627) return dentry; /* -error value */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 628)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 629) info->dir = cdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 630) info->entry = dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 631) info->num_subdirs = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 632)
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 633) /* adjust cdir to the optimized value */
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 634) cdir.dir = hint_opt.clu;
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 635) if (cdir.flags & ALLOC_NO_FAT_CHAIN)
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 636) cdir.size -= dentry / sbi->dentries_per_clu;
c6e2f52e3051e (Hyeongseok Kim 2021-03-22 12:53:36 +0900 637) dentry = hint_opt.eidx;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 638) es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 639) if (!es)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 640) return -EIO;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 641) ep = exfat_get_dentry_cached(es, 0);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 642) ep2 = exfat_get_dentry_cached(es, 1);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 643)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 644) info->type = exfat_get_entry_type(ep);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 645) info->attr = le16_to_cpu(ep->dentry.file.attr);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 646) info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 647) if ((info->type == TYPE_FILE) && (info->size == 0)) {
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 648) info->flags = ALLOC_NO_FAT_CHAIN;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 649) info->start_clu = EXFAT_EOF_CLUSTER;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 650) } else {
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 651) info->flags = ep2->dentry.stream.flags;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 652) info->start_clu =
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 653) le32_to_cpu(ep2->dentry.stream.start_clu);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 654) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 655)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 656) exfat_get_entry_time(sbi, &info->crtime,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 657) ep->dentry.file.create_tz,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 658) ep->dentry.file.create_time,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 659) ep->dentry.file.create_date,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 660) ep->dentry.file.create_time_cs);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 661) exfat_get_entry_time(sbi, &info->mtime,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 662) ep->dentry.file.modify_tz,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 663) ep->dentry.file.modify_time,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 664) ep->dentry.file.modify_date,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 665) ep->dentry.file.modify_time_cs);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 666) exfat_get_entry_time(sbi, &info->atime,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 667) ep->dentry.file.access_tz,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 668) ep->dentry.file.access_time,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 669) ep->dentry.file.access_date,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 670) 0);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 671) exfat_free_dentry_set(es, false);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 672)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 673) if (ei->start_clu == EXFAT_FREE_CLUSTER) {
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 674) exfat_fs_error(sb,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 675) "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)",
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 676) i_size_read(dir), ei->dir.dir, ei->entry);
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 677) return -EIO;
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 678) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 679)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 680) if (info->type == TYPE_DIR) {
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 681) exfat_chain_set(&cdir, info->start_clu,
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 682) EXFAT_B_TO_CLU(info->size, sbi), info->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 683) count = exfat_count_dir_entries(sb, &cdir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 684) if (count < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 685) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 686)
188df41f212c9 (Tetsuhiro Kohada 2020-09-02 16:53:06 +0900 687) info->num_subdirs = count + EXFAT_MIN_SUBDIR;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 688) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 689) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 690) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 691)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 692) static int exfat_d_anon_disconn(struct dentry *dentry)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 693) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 694) return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 695) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 696)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 697) static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 698) unsigned int flags)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 699) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 700) struct super_block *sb = dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 701) struct inode *inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 702) struct dentry *alias;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 703) struct exfat_dir_entry info;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 704) int err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 705) loff_t i_pos;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 706) mode_t i_mode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 707)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 708) mutex_lock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 709) err = exfat_find(dir, &dentry->d_name, &info);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 710) if (err) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 711) if (err == -ENOENT) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 712) inode = NULL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 713) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 714) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 715) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 716) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 717)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 718) i_pos = exfat_make_i_pos(&info);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 719) inode = exfat_build_inode(sb, &info, i_pos);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 720) err = PTR_ERR_OR_ZERO(inode);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 721) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 722) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 723)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 724) i_mode = inode->i_mode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 725) alias = d_find_alias(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 726)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 727) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 728) * Checking "alias->d_parent == dentry->d_parent" to make sure
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 729) * FS is not corrupted (especially double linked dir).
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 730) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 731) if (alias && alias->d_parent == dentry->d_parent &&
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 732) !exfat_d_anon_disconn(alias)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 733)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 734) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 735) * Unhashed alias is able to exist because of revalidate()
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 736) * called by lookup_fast. You can easily make this status
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 737) * by calling create and lookup concurrently
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 738) * In such case, we reuse an alias instead of new dentry
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 739) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 740) if (d_unhashed(alias)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 741) WARN_ON(alias->d_name.hash_len !=
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 742) dentry->d_name.hash_len);
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 743) exfat_info(sb, "rehashed a dentry(%p) in read lookup",
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 744) alias);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 745) d_drop(dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 746) d_rehash(alias);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 747) } else if (!S_ISDIR(i_mode)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 748) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 749) * This inode has non anonymous-DCACHE_DISCONNECTED
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 750) * dentry. This means, the user did ->lookup() by an
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 751) * another name (longname vs 8.3 alias of it) in past.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 752) *
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 753) * Switch to new one for reason of locality if possible.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 754) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 755) d_move(alias, dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 756) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 757) iput(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 758) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 759) return alias;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 760) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 761) dput(alias);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 762) out:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 763) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 764) if (!inode)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 765) exfat_d_version_set(dentry, inode_query_iversion(dir));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 766)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 767) return d_splice_alias(inode, dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 768) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 769) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 770) return ERR_PTR(err);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 771) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 772)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 773) /* remove an entry, BUT don't truncate */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 774) static int exfat_unlink(struct inode *dir, struct dentry *dentry)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 775) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 776) struct exfat_chain cdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 777) struct exfat_dentry *ep;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 778) struct super_block *sb = dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 779) struct inode *inode = dentry->d_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 780) struct exfat_inode_info *ei = EXFAT_I(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 781) struct buffer_head *bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 782) sector_t sector;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 783) int num_entries, entry, err = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 784)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 785) mutex_lock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 786) exfat_chain_dup(&cdir, &ei->dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 787) entry = ei->entry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 788) if (ei->dir.dir == DIR_DELETED) {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 789) exfat_err(sb, "abnormal access to deleted dentry");
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 790) err = -ENOENT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 791) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 792) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 793)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 794) ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 795) if (!ep) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 796) err = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 797) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 798) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 799) num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 800) if (num_entries < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 801) err = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 802) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 803) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 804) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 805) num_entries++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 806) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 807)
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 808) exfat_set_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 809) /* update the directory entry */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 810) if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 811) err = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 812) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 813) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 814)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 815) /* This doesn't modify ei */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 816) ei->dir.dir = DIR_DELETED;
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 817) exfat_clear_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 818)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 819) inode_inc_iversion(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 820) dir->i_mtime = dir->i_atime = current_time(dir);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 821) exfat_truncate_atime(&dir->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 822) if (IS_DIRSYNC(dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 823) exfat_sync_inode(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 824) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 825) mark_inode_dirty(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 826)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 827) clear_nlink(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 828) inode->i_mtime = inode->i_atime = current_time(inode);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 829) exfat_truncate_atime(&inode->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 830) exfat_unhash_inode(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 831) exfat_d_version_set(dentry, inode_query_iversion(dir));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 832) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 833) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 834) return err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 835) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 836)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 837) static int exfat_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 838) struct dentry *dentry, umode_t mode)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 839) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 840) struct super_block *sb = dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 841) struct inode *inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 842) struct exfat_dir_entry info;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 843) struct exfat_chain cdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 844) loff_t i_pos;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 845) int err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 846)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 847) mutex_lock(&EXFAT_SB(sb)->s_lock);
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 848) exfat_set_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 849) err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 850) &info);
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 851) exfat_clear_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 852) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 853) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 854)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 855) inode_inc_iversion(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 856) dir->i_ctime = dir->i_mtime = current_time(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 857) if (IS_DIRSYNC(dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 858) exfat_sync_inode(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 859) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 860) mark_inode_dirty(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 861) inc_nlink(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 862)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 863) i_pos = exfat_make_i_pos(&info);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 864) inode = exfat_build_inode(sb, &info, i_pos);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 865) err = PTR_ERR_OR_ZERO(inode);
d6c9efd92443b (Tetsuhiro Kohada 2020-08-26 10:18:29 +0900 866) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 867) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 868)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 869) inode_inc_iversion(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 870) inode->i_mtime = inode->i_atime = inode->i_ctime =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 871) EXFAT_I(inode)->i_crtime = current_time(inode);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 872) exfat_truncate_atime(&inode->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 873) /* timestamp is already written, so mark_inode_dirty() is unneeded. */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 874)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 875) d_instantiate(dentry, inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 876)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 877) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 878) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 879) return err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 880) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 881)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 882) static int exfat_check_dir_empty(struct super_block *sb,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 883) struct exfat_chain *p_dir)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 884) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 885) int i, dentries_per_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 886) unsigned int type;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 887) struct exfat_chain clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 888) struct exfat_dentry *ep;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 889) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 890) struct buffer_head *bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 891)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 892) dentries_per_clu = sbi->dentries_per_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 893)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 894) exfat_chain_dup(&clu, p_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 895)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 896) while (clu.dir != EXFAT_EOF_CLUSTER) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 897) for (i = 0; i < dentries_per_clu; i++) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 898) ep = exfat_get_dentry(sb, &clu, i, &bh, NULL);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 899) if (!ep)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 900) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 901) type = exfat_get_entry_type(ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 902) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 903) if (type == TYPE_UNUSED)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 904) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 905)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 906) if (type != TYPE_FILE && type != TYPE_DIR)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 907) continue;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 908)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 909) return -ENOTEMPTY;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 910) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 911)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 912) if (clu.flags == ALLOC_NO_FAT_CHAIN) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 913) if (--clu.size > 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 914) clu.dir++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 915) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 916) clu.dir = EXFAT_EOF_CLUSTER;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 917) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 918) if (exfat_get_next_cluster(sb, &(clu.dir)))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 919) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 920) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 921) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 922)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 923) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 924) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 925)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 926) static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 927) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 928) struct inode *inode = dentry->d_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 929) struct exfat_dentry *ep;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 930) struct exfat_chain cdir, clu_to_free;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 931) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 932) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 933) struct exfat_inode_info *ei = EXFAT_I(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 934) struct buffer_head *bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 935) sector_t sector;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 936) int num_entries, entry, err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 937)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 938) mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 939)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 940) exfat_chain_dup(&cdir, &ei->dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 941) entry = ei->entry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 942)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 943) if (ei->dir.dir == DIR_DELETED) {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 944) exfat_err(sb, "abnormal access to deleted dentry");
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 945) err = -ENOENT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 946) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 947) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 948)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 949) exfat_chain_set(&clu_to_free, ei->start_clu,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 950) EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 951)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 952) err = exfat_check_dir_empty(sb, &clu_to_free);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 953) if (err) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 954) if (err == -EIO)
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 955) exfat_err(sb, "failed to exfat_check_dir_empty : err(%d)",
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 956) err);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 957) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 958) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 959)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 960) ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 961) if (!ep) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 962) err = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 963) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 964) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 965)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 966) num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 967) if (num_entries < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 968) err = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 969) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 970) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 971) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 972) num_entries++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 973) brelse(bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 974)
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 975) exfat_set_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 976) err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 977) if (err) {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 978) exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 979) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 980) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 981) ei->dir.dir = DIR_DELETED;
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 982) exfat_clear_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 983)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 984) inode_inc_iversion(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 985) dir->i_mtime = dir->i_atime = current_time(dir);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 986) exfat_truncate_atime(&dir->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 987) if (IS_DIRSYNC(dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 988) exfat_sync_inode(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 989) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 990) mark_inode_dirty(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 991) drop_nlink(dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 992)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 993) clear_nlink(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 994) inode->i_mtime = inode->i_atime = current_time(inode);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 995) exfat_truncate_atime(&inode->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 996) exfat_unhash_inode(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 997) exfat_d_version_set(dentry, inode_query_iversion(dir));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 998) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 999) mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1000) return err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1001) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1002)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1003) static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1004) int oldentry, struct exfat_uni_name *p_uniname,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1005) struct exfat_inode_info *ei)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1006) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1007) int ret, num_old_entries, num_new_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1008) sector_t sector_old, sector_new;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1009) struct exfat_dentry *epold, *epnew;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1010) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1011) struct buffer_head *new_bh, *old_bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1012) int sync = IS_DIRSYNC(inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1013)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1014) epold = exfat_get_dentry(sb, p_dir, oldentry, &old_bh, §or_old);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1015) if (!epold)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1016) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1017)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1018) num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, epold);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1019) if (num_old_entries < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1020) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1021) num_old_entries++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1022)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1023) num_new_entries = exfat_calc_num_entries(p_uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1024) if (num_new_entries < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1025) return num_new_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1026)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1027) if (num_old_entries < num_new_entries) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1028) int newentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1029)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1030) newentry =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1031) exfat_find_empty_entry(inode, p_dir, num_new_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1032) if (newentry < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1033) return newentry; /* -EIO or -ENOSPC */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1034)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1035) epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1036) §or_new);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1037) if (!epnew)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1038) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1039)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 1040) *epnew = *epold;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1041) if (exfat_get_entry_type(epnew) == TYPE_FILE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1042) epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1043) ei->attr |= ATTR_ARCHIVE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1044) }
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 1045) exfat_update_bh(new_bh, sync);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1046) brelse(old_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1047) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1048)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1049) epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1050) §or_old);
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1051) if (!epold)
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1052) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1053) epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1054) §or_new);
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1055) if (!epnew) {
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1056) brelse(old_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1057) return -EIO;
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1058) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1059)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 1060) *epnew = *epold;
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 1061) exfat_update_bh(new_bh, sync);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1062) brelse(old_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1063) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1064)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1065) ret = exfat_init_ext_entry(inode, p_dir, newentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1066) num_new_entries, p_uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1067) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1068) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1069)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1070) exfat_remove_entries(inode, p_dir, oldentry, 0,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1071) num_old_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1072) ei->entry = newentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1073) } else {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1074) if (exfat_get_entry_type(epold) == TYPE_FILE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1075) epold->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1076) ei->attr |= ATTR_ARCHIVE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1077) }
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 1078) exfat_update_bh(old_bh, sync);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1079) brelse(old_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1080) ret = exfat_init_ext_entry(inode, p_dir, oldentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1081) num_new_entries, p_uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1082) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1083) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1084)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1085) exfat_remove_entries(inode, p_dir, oldentry, num_new_entries,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1086) num_old_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1087) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1088) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1089) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1090)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1091) static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1092) int oldentry, struct exfat_chain *p_newdir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1093) struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1094) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1095) int ret, newentry, num_new_entries, num_old_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1096) sector_t sector_mov, sector_new;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1097) struct exfat_dentry *epmov, *epnew;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1098) struct super_block *sb = inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1099) struct buffer_head *mov_bh, *new_bh;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1100)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1101) epmov = exfat_get_dentry(sb, p_olddir, oldentry, &mov_bh, §or_mov);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1102) if (!epmov)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1103) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1104)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1105) num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1106) epmov);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1107) if (num_old_entries < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1108) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1109) num_old_entries++;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1110)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1111) num_new_entries = exfat_calc_num_entries(p_uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1112) if (num_new_entries < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1113) return num_new_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1114)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1115) newentry = exfat_find_empty_entry(inode, p_newdir, num_new_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1116) if (newentry < 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1117) return newentry; /* -EIO or -ENOSPC */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1118)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1119) epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh, §or_new);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1120) if (!epnew)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1121) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1122)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 1123) *epnew = *epmov;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1124) if (exfat_get_entry_type(epnew) == TYPE_FILE) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1125) epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1126) ei->attr |= ATTR_ARCHIVE;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1127) }
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 1128) exfat_update_bh(new_bh, IS_DIRSYNC(inode));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1129) brelse(mov_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1130) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1131)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1132) epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1133) §or_mov);
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1134) if (!epmov)
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1135) return -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1136) epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1137) §or_new);
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1138) if (!epnew) {
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1139) brelse(mov_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1140) return -EIO;
e8dd3cda86671 (Dan Carpenter 2020-06-10 20:22:13 +0300 1141) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1142)
a7a241686c8f8 (Tetsuhiro Kohada 2020-09-11 13:45:19 +0900 1143) *epnew = *epmov;
2c7f8937ef915 (Tetsuhiro Kohada 2020-06-16 11:18:07 +0900 1144) exfat_update_bh(new_bh, IS_DIRSYNC(inode));
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1145) brelse(mov_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1146) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1147)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1148) ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1149) p_uniname);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1150) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1151) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1152)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1153) exfat_remove_entries(inode, p_olddir, oldentry, 0, num_old_entries);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1154)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1155) exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1156) p_newdir->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1157)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1158) ei->entry = newentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1159) return 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1160) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1161)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1162) static void exfat_update_parent_info(struct exfat_inode_info *ei,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1163) struct inode *parent_inode)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1164) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1165) struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1166) struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1167) loff_t parent_isize = i_size_read(parent_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1168)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1169) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1170) * the problem that struct exfat_inode_info caches wrong parent info.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1171) *
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1172) * because of flag-mismatch of ei->dir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1173) * there is abnormal traversing cluster chain.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1174) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1175) if (unlikely(parent_ei->flags != ei->dir.flags ||
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1176) parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) ||
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1177) parent_ei->start_clu != ei->dir.dir)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1178) exfat_chain_set(&ei->dir, parent_ei->start_clu,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1179) EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi),
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1180) parent_ei->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1181) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1182) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1183)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1184) /* rename or move a old file into a new file */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1185) static int __exfat_rename(struct inode *old_parent_inode,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1186) struct exfat_inode_info *ei, struct inode *new_parent_inode,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1187) struct dentry *new_dentry)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1188) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1189) int ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1190) int dentry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1191) struct exfat_chain olddir, newdir;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1192) struct exfat_chain *p_dir = NULL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1193) struct exfat_uni_name uni_name;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1194) struct exfat_dentry *ep;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1195) struct super_block *sb = old_parent_inode->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1196) struct exfat_sb_info *sbi = EXFAT_SB(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1197) const unsigned char *new_path = new_dentry->d_name.name;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1198) struct inode *new_inode = new_dentry->d_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1199) int num_entries;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1200) struct exfat_inode_info *new_ei = NULL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1201) unsigned int new_entry_type = TYPE_UNUSED;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1202) int new_entry = 0;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1203) struct buffer_head *old_bh, *new_bh = NULL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1204)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1205) /* check the validity of pointer parameters */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1206) if (new_path == NULL || strlen(new_path) == 0)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1207) return -EINVAL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1208)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1209) if (ei->dir.dir == DIR_DELETED) {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 1210) exfat_err(sb, "abnormal access to deleted source dentry");
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1211) return -ENOENT;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1212) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1213)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1214) exfat_update_parent_info(ei, old_parent_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1215)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1216) exfat_chain_dup(&olddir, &ei->dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1217) dentry = ei->entry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1218)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1219) ep = exfat_get_dentry(sb, &olddir, dentry, &old_bh, NULL);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1220) if (!ep) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1221) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1222) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1223) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1224) brelse(old_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1225)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1226) /* check whether new dir is existing directory and empty */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1227) if (new_inode) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1228) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1229) new_ei = EXFAT_I(new_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1230)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1231) if (new_ei->dir.dir == DIR_DELETED) {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 1232) exfat_err(sb, "abnormal access to deleted target dentry");
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1233) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1234) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1235)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1236) exfat_update_parent_info(new_ei, new_parent_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1237)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1238) p_dir = &(new_ei->dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1239) new_entry = new_ei->entry;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1240) ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1241) if (!ep)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1242) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1243)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1244) new_entry_type = exfat_get_entry_type(ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1245) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1246)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1247) /* if new_inode exists, update ei */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1248) if (new_entry_type == TYPE_DIR) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1249) struct exfat_chain new_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1250)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1251) new_clu.dir = new_ei->start_clu;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1252) new_clu.size =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1253) EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode),
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1254) sbi);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1255) new_clu.flags = new_ei->flags;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1256)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1257) ret = exfat_check_dir_empty(sb, &new_clu);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1258) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1259) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1260) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1261) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1262)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1263) /* check the validity of directory name in the given new pathname */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1264) ret = exfat_resolve_path(new_parent_inode, new_path, &newdir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1265) &uni_name);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1266) if (ret)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1267) goto out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1268)
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 1269) exfat_set_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1270)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1271) if (olddir.dir == newdir.dir)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1272) ret = exfat_rename_file(new_parent_inode, &olddir, dentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1273) &uni_name, ei);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1274) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1275) ret = exfat_move_file(new_parent_inode, &olddir, dentry,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1276) &newdir, &uni_name, ei);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1277)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1278) if (!ret && new_inode) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1279) /* delete entries of new_dir */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1280) ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1281) if (!ep) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1282) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1283) goto del_out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1284) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1285)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1286) num_entries = exfat_count_ext_entries(sb, p_dir, new_entry, ep);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1287) if (num_entries < 0) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1288) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1289) goto del_out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1290) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1291) brelse(new_bh);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1292)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1293) if (exfat_remove_entries(new_inode, p_dir, new_entry, 0,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1294) num_entries + 1)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1295) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1296) goto del_out;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1297) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1298)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1299) /* Free the clusters if new_inode is a dir(as if exfat_rmdir) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1300) if (new_entry_type == TYPE_DIR) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1301) /* new_ei, new_clu_to_free */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1302) struct exfat_chain new_clu_to_free;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1303)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1304) exfat_chain_set(&new_clu_to_free, new_ei->start_clu,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1305) EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode),
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1306) sbi), new_ei->flags);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1307)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1308) if (exfat_free_cluster(new_inode, &new_clu_to_free)) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1309) /* just set I/O error only */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1310) ret = -EIO;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1311) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1312)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1313) i_size_write(new_inode, 0);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1314) new_ei->start_clu = EXFAT_EOF_CLUSTER;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1315) new_ei->flags = ALLOC_NO_FAT_CHAIN;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1316) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1317) del_out:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1318) /* Update new_inode ei
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1319) * Prevent syncing removed new_inode
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1320) * (new_ei is already initialized above code ("if (new_inode)")
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1321) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1322) new_ei->dir.dir = DIR_DELETED;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1323) }
7018ec68f0824 (Tetsuhiro Kohada 2020-07-31 14:58:26 +0900 1324) exfat_clear_volume_dirty(sb);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1325) out:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1326) return ret;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1327) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1328)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1329) static int exfat_rename(struct user_namespace *mnt_userns,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1330) struct inode *old_dir, struct dentry *old_dentry,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1331) struct inode *new_dir, struct dentry *new_dentry,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 1332) unsigned int flags)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1333) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1334) struct inode *old_inode, *new_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1335) struct super_block *sb = old_dir->i_sb;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1336) loff_t i_pos;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1337) int err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1338)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1339) /*
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1340) * The VFS already checks for existence, so for local filesystems
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1341) * the RENAME_NOREPLACE implementation is equivalent to plain rename.
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1342) * Don't support any other flags
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1343) */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1344) if (flags & ~RENAME_NOREPLACE)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1345) return -EINVAL;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1346)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1347) mutex_lock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1348) old_inode = old_dentry->d_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1349) new_inode = new_dentry->d_inode;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1350)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1351) err = __exfat_rename(old_dir, EXFAT_I(old_inode), new_dir, new_dentry);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1352) if (err)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1353) goto unlock;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1354)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1355) inode_inc_iversion(new_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1356) new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1357) EXFAT_I(new_dir)->i_crtime = current_time(new_dir);
81df1ad40644b (Eric Sandeen 2020-04-21 11:13:10 +0900 1358) exfat_truncate_atime(&new_dir->i_atime);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1359) if (IS_DIRSYNC(new_dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1360) exfat_sync_inode(new_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1361) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1362) mark_inode_dirty(new_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1363)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1364) i_pos = ((loff_t)EXFAT_I(old_inode)->dir.dir << 32) |
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1365) (EXFAT_I(old_inode)->entry & 0xffffffff);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1366) exfat_unhash_inode(old_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1367) exfat_hash_inode(old_inode, i_pos);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1368) if (IS_DIRSYNC(new_dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1369) exfat_sync_inode(old_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1370) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1371) mark_inode_dirty(old_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1372)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1373) if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1374) drop_nlink(old_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1375) if (!new_inode)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1376) inc_nlink(new_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1377) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1378)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1379) inode_inc_iversion(old_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1380) old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1381) if (IS_DIRSYNC(old_dir))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1382) exfat_sync_inode(old_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1383) else
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1384) mark_inode_dirty(old_dir);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1385)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1386) if (new_inode) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1387) exfat_unhash_inode(new_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1388)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1389) /* skip drop_nlink if new_inode already has been dropped */
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1390) if (new_inode->i_nlink) {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1391) drop_nlink(new_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1392) if (S_ISDIR(new_inode->i_mode))
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1393) drop_nlink(new_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1394) } else {
d1727d55c0327 (Joe Perches 2020-04-24 13:31:12 +0900 1395) exfat_warn(sb, "abnormal access to an inode dropped");
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1396) WARN_ON(new_inode->i_nlink == 0);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1397) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1398) new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime =
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1399) current_time(new_inode);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1400) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1401)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1402) unlock:
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1403) mutex_unlock(&EXFAT_SB(sb)->s_lock);
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1404) return err;
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1405) }
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1406)
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1407) const struct inode_operations exfat_dir_inode_operations = {
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1408) .create = exfat_create,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1409) .lookup = exfat_lookup,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1410) .unlink = exfat_unlink,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1411) .mkdir = exfat_mkdir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1412) .rmdir = exfat_rmdir,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1413) .rename = exfat_rename,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1414) .setattr = exfat_setattr,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1415) .getattr = exfat_getattr,
5f2aa075070cf (Namjae Jeon 2020-03-02 15:21:34 +0900 1416) };