^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* fs/fat/nfs.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/exportfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "fat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct fat_fid {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) u32 i_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) u32 i_pos_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) u16 i_pos_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) u16 parent_i_pos_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) u32 parent_i_pos_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) u32 parent_i_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define FAT_FID_SIZE_WITHOUT_PARENT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define FAT_FID_SIZE_WITH_PARENT (sizeof(struct fat_fid)/sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Look up a directory inode given its starting cluster.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static struct inode *fat_dget(struct super_block *sb, int i_logstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct msdos_sb_info *sbi = MSDOS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct msdos_inode_info *i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) spin_lock(&sbi->dir_hash_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) hlist_for_each_entry(i, head, i_dir_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) BUG_ON(i->vfs_inode.i_sb != sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (i->i_logstart != i_logstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) inode = igrab(&i->vfs_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) spin_unlock(&sbi->dir_hash_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static struct inode *fat_ilookup(struct super_block *sb, u64 ino, loff_t i_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return fat_iget(sb, i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return ilookup(sb, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct inode *__fat_nfs_get_inode(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u64 ino, u32 generation, loff_t i_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct inode *inode = fat_ilookup(sb, ino, i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (inode && generation && (inode->i_generation != generation)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct msdos_dir_entry *de ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sector_t blocknr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) bh = sb_bread(sb, blocknr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) fat_msg(sb, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "unable to read block(%llu) for building NFS inode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) (llu)blocknr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) de = (struct msdos_dir_entry *)bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* If a file is deleted on server and client is not updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * yet, we must not build the inode upon a lookup call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (IS_FREE(de[offset].name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) inode = fat_build_inode(sb, &de[offset], i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static struct inode *fat_nfs_get_inode(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u64 ino, u32 generation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return __fat_nfs_get_inode(sb, ino, generation, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct inode *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int len = *lenp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct fat_fid *fid = (struct fat_fid *) fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) loff_t i_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int type = FILEID_FAT_WITHOUT_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (len < FAT_FID_SIZE_WITH_PARENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *lenp = FAT_FID_SIZE_WITH_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return FILEID_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (len < FAT_FID_SIZE_WITHOUT_PARENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *lenp = FAT_FID_SIZE_WITHOUT_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return FILEID_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) i_pos = fat_i_pos_read(sbi, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *lenp = FAT_FID_SIZE_WITHOUT_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fid->i_gen = inode->i_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fid->i_pos_low = i_pos & 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) fid->i_pos_hi = (i_pos >> 32) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) i_pos = fat_i_pos_read(sbi, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fid->parent_i_pos_hi = (i_pos >> 32) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) fid->parent_i_pos_low = i_pos & 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) fid->parent_i_gen = parent->i_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) type = FILEID_FAT_WITH_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *lenp = FAT_FID_SIZE_WITH_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Map a NFS file handle to a corresponding dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * The dentry may or may not be connected to the filesystem root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int fh_len, int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) fat_nfs_get_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static struct dentry *fat_fh_to_dentry_nostale(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct fid *fh, int fh_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct fat_fid *fid = (struct fat_fid *)fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) loff_t i_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) switch (fh_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case FILEID_FAT_WITHOUT_PARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (fh_len < FAT_FID_SIZE_WITHOUT_PARENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case FILEID_FAT_WITH_PARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (fh_len < FAT_FID_SIZE_WITH_PARENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) i_pos = fid->i_pos_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) i_pos = (i_pos << 32) | (fid->i_pos_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) inode = __fat_nfs_get_inode(sb, 0, fid->i_gen, i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return d_obtain_alias(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * Find the parent for a file specified by NFS handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * This requires that the handle contain the i_ino of the parent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int fh_len, int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return generic_fh_to_parent(sb, fid, fh_len, fh_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) fat_nfs_get_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static struct dentry *fat_fh_to_parent_nostale(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct fid *fh, int fh_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct fat_fid *fid = (struct fat_fid *)fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) loff_t i_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (fh_len < FAT_FID_SIZE_WITH_PARENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) switch (fh_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case FILEID_FAT_WITH_PARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) i_pos = fid->parent_i_pos_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) i_pos = (i_pos << 32) | (fid->parent_i_pos_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) inode = __fat_nfs_get_inode(sb, 0, fid->parent_i_gen, i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return d_obtain_alias(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Rebuild the parent for a directory that is not connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * to the filesystem root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int search_clus, clus_to_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct msdos_dir_entry *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct inode *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct inode *dummy_grand_parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct fat_slot_info sinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct msdos_sb_info *sbi = MSDOS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) sector_t blknr = fat_clus_to_blknr(sbi, parent_logstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct buffer_head *parent_bh = sb_bread(sb, blknr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (!parent_bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fat_msg(sb, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "unable to read cluster of parent directory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) de = (struct msdos_dir_entry *) parent_bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) clus_to_match = fat_get_start(sbi, &de[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) search_clus = fat_get_start(sbi, &de[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dummy_grand_parent = fat_dget(sb, search_clus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (!dummy_grand_parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) dummy_grand_parent = new_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!dummy_grand_parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) brelse(parent_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dummy_grand_parent->i_ino = iunique(sb, MSDOS_ROOT_INO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) fat_fill_inode(dummy_grand_parent, &de[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) MSDOS_I(dummy_grand_parent)->i_pos = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!fat_scan_logstart(dummy_grand_parent, clus_to_match, &sinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) parent = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) brelse(parent_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) iput(dummy_grand_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Find the parent for a directory that is not currently connected to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * the filesystem root.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * On entry, the caller holds d_inode(child_dir)->i_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static struct dentry *fat_get_parent(struct dentry *child_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct super_block *sb = child_dir->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct msdos_dir_entry *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct inode *parent_inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct msdos_sb_info *sbi = MSDOS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!fat_get_dotdot_entry(d_inode(child_dir), &bh, &de)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int parent_logstart = fat_get_start(sbi, de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) parent_inode = fat_dget(sb, parent_logstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) parent_inode = fat_rebuild_parent(sb, parent_logstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return d_obtain_alias(parent_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) const struct export_operations fat_export_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .fh_to_dentry = fat_fh_to_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .fh_to_parent = fat_fh_to_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .get_parent = fat_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) const struct export_operations fat_export_ops_nostale = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .encode_fh = fat_encode_fh_nostale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .fh_to_dentry = fat_fh_to_dentry_nostale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .fh_to_parent = fat_fh_to_parent_nostale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .get_parent = fat_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) };