diff options
-rw-r--r-- | fs/libfs.c | 96 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
2 files changed, 98 insertions, 0 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index cb1fb4b9b637..02813592e121 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -1093,3 +1093,99 @@ simple_nosetlease(struct file *filp, long arg, struct file_lock **flp, | |||
1093 | return -EINVAL; | 1093 | return -EINVAL; |
1094 | } | 1094 | } |
1095 | EXPORT_SYMBOL(simple_nosetlease); | 1095 | EXPORT_SYMBOL(simple_nosetlease); |
1096 | |||
1097 | |||
1098 | /* | ||
1099 | * Operations for a permanently empty directory. | ||
1100 | */ | ||
1101 | static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | ||
1102 | { | ||
1103 | return ERR_PTR(-ENOENT); | ||
1104 | } | ||
1105 | |||
1106 | static int empty_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
1107 | struct kstat *stat) | ||
1108 | { | ||
1109 | struct inode *inode = d_inode(dentry); | ||
1110 | generic_fillattr(inode, stat); | ||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr) | ||
1115 | { | ||
1116 | return -EPERM; | ||
1117 | } | ||
1118 | |||
1119 | static int empty_dir_setxattr(struct dentry *dentry, const char *name, | ||
1120 | const void *value, size_t size, int flags) | ||
1121 | { | ||
1122 | return -EOPNOTSUPP; | ||
1123 | } | ||
1124 | |||
1125 | static ssize_t empty_dir_getxattr(struct dentry *dentry, const char *name, | ||
1126 | void *value, size_t size) | ||
1127 | { | ||
1128 | return -EOPNOTSUPP; | ||
1129 | } | ||
1130 | |||
1131 | static int empty_dir_removexattr(struct dentry *dentry, const char *name) | ||
1132 | { | ||
1133 | return -EOPNOTSUPP; | ||
1134 | } | ||
1135 | |||
1136 | static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size) | ||
1137 | { | ||
1138 | return -EOPNOTSUPP; | ||
1139 | } | ||
1140 | |||
1141 | static const struct inode_operations empty_dir_inode_operations = { | ||
1142 | .lookup = empty_dir_lookup, | ||
1143 | .permission = generic_permission, | ||
1144 | .setattr = empty_dir_setattr, | ||
1145 | .getattr = empty_dir_getattr, | ||
1146 | .setxattr = empty_dir_setxattr, | ||
1147 | .getxattr = empty_dir_getxattr, | ||
1148 | .removexattr = empty_dir_removexattr, | ||
1149 | .listxattr = empty_dir_listxattr, | ||
1150 | }; | ||
1151 | |||
1152 | static loff_t empty_dir_llseek(struct file *file, loff_t offset, int whence) | ||
1153 | { | ||
1154 | /* An empty directory has two entries . and .. at offsets 0 and 1 */ | ||
1155 | return generic_file_llseek_size(file, offset, whence, 2, 2); | ||
1156 | } | ||
1157 | |||
1158 | static int empty_dir_readdir(struct file *file, struct dir_context *ctx) | ||
1159 | { | ||
1160 | dir_emit_dots(file, ctx); | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | static const struct file_operations empty_dir_operations = { | ||
1165 | .llseek = empty_dir_llseek, | ||
1166 | .read = generic_read_dir, | ||
1167 | .iterate = empty_dir_readdir, | ||
1168 | .fsync = noop_fsync, | ||
1169 | }; | ||
1170 | |||
1171 | |||
1172 | void make_empty_dir_inode(struct inode *inode) | ||
1173 | { | ||
1174 | set_nlink(inode, 2); | ||
1175 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
1176 | inode->i_uid = GLOBAL_ROOT_UID; | ||
1177 | inode->i_gid = GLOBAL_ROOT_GID; | ||
1178 | inode->i_rdev = 0; | ||
1179 | inode->i_size = 2; | ||
1180 | inode->i_blkbits = PAGE_SHIFT; | ||
1181 | inode->i_blocks = 0; | ||
1182 | |||
1183 | inode->i_op = &empty_dir_inode_operations; | ||
1184 | inode->i_fop = &empty_dir_operations; | ||
1185 | } | ||
1186 | |||
1187 | bool is_empty_dir_inode(struct inode *inode) | ||
1188 | { | ||
1189 | return (inode->i_fop == &empty_dir_operations) && | ||
1190 | (inode->i_op == &empty_dir_inode_operations); | ||
1191 | } | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 35ec87e490b1..0d5ae7d5dc53 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2780,6 +2780,8 @@ extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned in | |||
2780 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); | 2780 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); |
2781 | extern const struct file_operations simple_dir_operations; | 2781 | extern const struct file_operations simple_dir_operations; |
2782 | extern const struct inode_operations simple_dir_inode_operations; | 2782 | extern const struct inode_operations simple_dir_inode_operations; |
2783 | extern void make_empty_dir_inode(struct inode *inode); | ||
2784 | extern bool is_empty_dir_inode(struct inode *inode); | ||
2783 | struct tree_descr { char *name; const struct file_operations *ops; int mode; }; | 2785 | struct tree_descr { char *name; const struct file_operations *ops; int mode; }; |
2784 | struct dentry *d_alloc_name(struct dentry *, const char *); | 2786 | struct dentry *d_alloc_name(struct dentry *, const char *); |
2785 | extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *); | 2787 | extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *); |