@@ -1155,6 +1155,143 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11551155 return 0 ;
11561156}
11571157
1158+ static int fuse_direntplus_link (struct file * file ,
1159+ struct fuse_direntplus * direntplus ,
1160+ u64 attr_version )
1161+ {
1162+ int err ;
1163+ struct fuse_entry_out * o = & direntplus -> entry_out ;
1164+ struct fuse_dirent * dirent = & direntplus -> dirent ;
1165+ struct dentry * parent = file -> f_path .dentry ;
1166+ struct qstr name = QSTR_INIT (dirent -> name , dirent -> namelen );
1167+ struct dentry * dentry ;
1168+ struct dentry * alias ;
1169+ struct inode * dir = parent -> d_inode ;
1170+ struct fuse_conn * fc ;
1171+ struct inode * inode ;
1172+
1173+ if (!o -> nodeid ) {
1174+ /*
1175+ * Unlike in the case of fuse_lookup, zero nodeid does not mean
1176+ * ENOENT. Instead, it only means the userspace filesystem did
1177+ * not want to return attributes/handle for this entry.
1178+ *
1179+ * So do nothing.
1180+ */
1181+ return 0 ;
1182+ }
1183+
1184+ if (name .name [0 ] == '.' ) {
1185+ /*
1186+ * We could potentially refresh the attributes of the directory
1187+ * and its parent?
1188+ */
1189+ if (name .len == 1 )
1190+ return 0 ;
1191+ if (name .name [1 ] == '.' && name .len == 2 )
1192+ return 0 ;
1193+ }
1194+ fc = get_fuse_conn (dir );
1195+
1196+ name .hash = full_name_hash (name .name , name .len );
1197+ dentry = d_lookup (parent , & name );
1198+ if (dentry && dentry -> d_inode ) {
1199+ inode = dentry -> d_inode ;
1200+ if (get_node_id (inode ) == o -> nodeid ) {
1201+ struct fuse_inode * fi ;
1202+ fi = get_fuse_inode (inode );
1203+ spin_lock (& fc -> lock );
1204+ fi -> nlookup ++ ;
1205+ spin_unlock (& fc -> lock );
1206+
1207+ /*
1208+ * The other branch to 'found' comes via fuse_iget()
1209+ * which bumps nlookup inside
1210+ */
1211+ goto found ;
1212+ }
1213+ err = d_invalidate (dentry );
1214+ if (err )
1215+ goto out ;
1216+ dput (dentry );
1217+ dentry = NULL ;
1218+ }
1219+
1220+ dentry = d_alloc (parent , & name );
1221+ err = - ENOMEM ;
1222+ if (!dentry )
1223+ goto out ;
1224+
1225+ inode = fuse_iget (dir -> i_sb , o -> nodeid , o -> generation ,
1226+ & o -> attr , entry_attr_timeout (o ), attr_version );
1227+ if (!inode )
1228+ goto out ;
1229+
1230+ alias = d_materialise_unique (dentry , inode );
1231+ err = PTR_ERR (alias );
1232+ if (IS_ERR (alias ))
1233+ goto out ;
1234+ if (alias ) {
1235+ dput (dentry );
1236+ dentry = alias ;
1237+ }
1238+
1239+ found :
1240+ fuse_change_attributes (inode , & o -> attr , entry_attr_timeout (o ),
1241+ attr_version );
1242+
1243+ fuse_change_entry_timeout (dentry , o );
1244+
1245+ err = 0 ;
1246+ out :
1247+ if (dentry )
1248+ dput (dentry );
1249+ return err ;
1250+ }
1251+
1252+ static int parse_dirplusfile (char * buf , size_t nbytes , struct file * file ,
1253+ void * dstbuf , filldir_t filldir , u64 attr_version )
1254+ {
1255+ struct fuse_direntplus * direntplus ;
1256+ struct fuse_dirent * dirent ;
1257+ size_t reclen ;
1258+ int over = 0 ;
1259+ int ret ;
1260+
1261+ while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS ) {
1262+ direntplus = (struct fuse_direntplus * ) buf ;
1263+ dirent = & direntplus -> dirent ;
1264+ reclen = FUSE_DIRENTPLUS_SIZE (direntplus );
1265+
1266+ if (!dirent -> namelen || dirent -> namelen > FUSE_NAME_MAX )
1267+ return - EIO ;
1268+ if (reclen > nbytes )
1269+ break ;
1270+
1271+ if (!over ) {
1272+ /* We fill entries into dstbuf only as much as
1273+ it can hold. But we still continue iterating
1274+ over remaining entries to link them. If not,
1275+ we need to send a FORGET for each of those
1276+ which we did not link.
1277+ */
1278+ over = filldir (dstbuf , dirent -> name , dirent -> namelen ,
1279+ file -> f_pos , dirent -> ino ,
1280+ dirent -> type );
1281+ file -> f_pos = dirent -> off ;
1282+ }
1283+
1284+ buf += reclen ;
1285+ nbytes -= reclen ;
1286+
1287+ ret = fuse_direntplus_link (file , direntplus , attr_version );
1288+ if (ret )
1289+ fuse_force_forget (file , direntplus -> entry_out .nodeid );
1290+ }
1291+
1292+ return 0 ;
1293+ }
1294+
11581295static int fuse_readdir (struct file * file , void * dstbuf , filldir_t filldir )
11591296{
11601297 int err ;
@@ -1163,6 +1300,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
11631300 struct inode * inode = file -> f_path .dentry -> d_inode ;
11641301 struct fuse_conn * fc = get_fuse_conn (inode );
11651302 struct fuse_req * req ;
1303+ u64 attr_version = 0 ;
11661304
11671305 if (is_bad_inode (inode ))
11681306 return - EIO ;
@@ -1179,14 +1317,28 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
11791317 req -> out .argpages = 1 ;
11801318 req -> num_pages = 1 ;
11811319 req -> pages [0 ] = page ;
1182- fuse_read_fill (req , file , file -> f_pos , PAGE_SIZE , FUSE_READDIR );
1320+ if (fc -> do_readdirplus ) {
1321+ attr_version = fuse_get_attr_version (fc );
1322+ fuse_read_fill (req , file , file -> f_pos , PAGE_SIZE ,
1323+ FUSE_READDIRPLUS );
1324+ } else {
1325+ fuse_read_fill (req , file , file -> f_pos , PAGE_SIZE ,
1326+ FUSE_READDIR );
1327+ }
11831328 fuse_request_send (fc , req );
11841329 nbytes = req -> out .args [0 ].size ;
11851330 err = req -> out .h .error ;
11861331 fuse_put_request (fc , req );
1187- if (!err )
1188- err = parse_dirfile (page_address (page ), nbytes , file , dstbuf ,
1189- filldir );
1332+ if (!err ) {
1333+ if (fc -> do_readdirplus ) {
1334+ err = parse_dirplusfile (page_address (page ), nbytes ,
1335+ file , dstbuf , filldir ,
1336+ attr_version );
1337+ } else {
1338+ err = parse_dirfile (page_address (page ), nbytes , file ,
1339+ dstbuf , filldir );
1340+ }
1341+ }
11901342
11911343 __free_page (page );
11921344 fuse_invalidate_attr (inode ); /* atime changed */
0 commit comments