162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved 462306a36Sopenharmony_ci * Copyright 2005-2006 Ian Kent <raven@themaw.net> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/seq_file.h> 862306a36Sopenharmony_ci#include <linux/pagemap.h> 962306a36Sopenharmony_ci#include <linux/parser.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "autofs_i.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct autofs_info *autofs_new_ino(struct autofs_sb_info *sbi) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct autofs_info *ino; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci ino = kzalloc(sizeof(*ino), GFP_KERNEL); 1862306a36Sopenharmony_ci if (ino) { 1962306a36Sopenharmony_ci INIT_LIST_HEAD(&ino->active); 2062306a36Sopenharmony_ci INIT_LIST_HEAD(&ino->expiring); 2162306a36Sopenharmony_ci ino->last_used = jiffies; 2262306a36Sopenharmony_ci ino->sbi = sbi; 2362306a36Sopenharmony_ci ino->count = 1; 2462306a36Sopenharmony_ci } 2562306a36Sopenharmony_ci return ino; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_civoid autofs_clean_ino(struct autofs_info *ino) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci ino->uid = GLOBAL_ROOT_UID; 3162306a36Sopenharmony_ci ino->gid = GLOBAL_ROOT_GID; 3262306a36Sopenharmony_ci ino->last_used = jiffies; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_civoid autofs_free_ino(struct autofs_info *ino) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci kfree_rcu(ino, rcu); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_civoid autofs_kill_sb(struct super_block *sb) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(sb); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * In the event of a failure in get_sb_nodev the superblock 4662306a36Sopenharmony_ci * info is not present so nothing else has been setup, so 4762306a36Sopenharmony_ci * just call kill_anon_super when we are called from 4862306a36Sopenharmony_ci * deactivate_super. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci if (sbi) { 5162306a36Sopenharmony_ci /* Free wait queues, close pipe */ 5262306a36Sopenharmony_ci autofs_catatonic_mode(sbi); 5362306a36Sopenharmony_ci put_pid(sbi->oz_pgrp); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci pr_debug("shutting down\n"); 5762306a36Sopenharmony_ci kill_litter_super(sb); 5862306a36Sopenharmony_ci if (sbi) 5962306a36Sopenharmony_ci kfree_rcu(sbi, rcu); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic int autofs_show_options(struct seq_file *m, struct dentry *root) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(root->d_sb); 6562306a36Sopenharmony_ci struct inode *root_inode = d_inode(root->d_sb->s_root); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (!sbi) 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci seq_printf(m, ",fd=%d", sbi->pipefd); 7162306a36Sopenharmony_ci if (!uid_eq(root_inode->i_uid, GLOBAL_ROOT_UID)) 7262306a36Sopenharmony_ci seq_printf(m, ",uid=%u", 7362306a36Sopenharmony_ci from_kuid_munged(&init_user_ns, root_inode->i_uid)); 7462306a36Sopenharmony_ci if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID)) 7562306a36Sopenharmony_ci seq_printf(m, ",gid=%u", 7662306a36Sopenharmony_ci from_kgid_munged(&init_user_ns, root_inode->i_gid)); 7762306a36Sopenharmony_ci seq_printf(m, ",pgrp=%d", pid_vnr(sbi->oz_pgrp)); 7862306a36Sopenharmony_ci seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); 7962306a36Sopenharmony_ci seq_printf(m, ",minproto=%d", sbi->min_proto); 8062306a36Sopenharmony_ci seq_printf(m, ",maxproto=%d", sbi->max_proto); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (autofs_type_offset(sbi->type)) 8362306a36Sopenharmony_ci seq_puts(m, ",offset"); 8462306a36Sopenharmony_ci else if (autofs_type_direct(sbi->type)) 8562306a36Sopenharmony_ci seq_puts(m, ",direct"); 8662306a36Sopenharmony_ci else 8762306a36Sopenharmony_ci seq_puts(m, ",indirect"); 8862306a36Sopenharmony_ci if (sbi->flags & AUTOFS_SBI_STRICTEXPIRE) 8962306a36Sopenharmony_ci seq_puts(m, ",strictexpire"); 9062306a36Sopenharmony_ci if (sbi->flags & AUTOFS_SBI_IGNORE) 9162306a36Sopenharmony_ci seq_puts(m, ",ignore"); 9262306a36Sopenharmony_ci#ifdef CONFIG_CHECKPOINT_RESTORE 9362306a36Sopenharmony_ci if (sbi->pipe) 9462306a36Sopenharmony_ci seq_printf(m, ",pipe_ino=%ld", file_inode(sbi->pipe)->i_ino); 9562306a36Sopenharmony_ci else 9662306a36Sopenharmony_ci seq_puts(m, ",pipe_ino=-1"); 9762306a36Sopenharmony_ci#endif 9862306a36Sopenharmony_ci return 0; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void autofs_evict_inode(struct inode *inode) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci clear_inode(inode); 10462306a36Sopenharmony_ci kfree(inode->i_private); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic const struct super_operations autofs_sops = { 10862306a36Sopenharmony_ci .statfs = simple_statfs, 10962306a36Sopenharmony_ci .show_options = autofs_show_options, 11062306a36Sopenharmony_ci .evict_inode = autofs_evict_inode, 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cienum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, 11462306a36Sopenharmony_ci Opt_indirect, Opt_direct, Opt_offset, Opt_strictexpire, 11562306a36Sopenharmony_ci Opt_ignore}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic const match_table_t tokens = { 11862306a36Sopenharmony_ci {Opt_fd, "fd=%u"}, 11962306a36Sopenharmony_ci {Opt_uid, "uid=%u"}, 12062306a36Sopenharmony_ci {Opt_gid, "gid=%u"}, 12162306a36Sopenharmony_ci {Opt_pgrp, "pgrp=%u"}, 12262306a36Sopenharmony_ci {Opt_minproto, "minproto=%u"}, 12362306a36Sopenharmony_ci {Opt_maxproto, "maxproto=%u"}, 12462306a36Sopenharmony_ci {Opt_indirect, "indirect"}, 12562306a36Sopenharmony_ci {Opt_direct, "direct"}, 12662306a36Sopenharmony_ci {Opt_offset, "offset"}, 12762306a36Sopenharmony_ci {Opt_strictexpire, "strictexpire"}, 12862306a36Sopenharmony_ci {Opt_ignore, "ignore"}, 12962306a36Sopenharmony_ci {Opt_err, NULL} 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int parse_options(char *options, 13362306a36Sopenharmony_ci struct inode *root, int *pgrp, bool *pgrp_set, 13462306a36Sopenharmony_ci struct autofs_sb_info *sbi) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci char *p; 13762306a36Sopenharmony_ci substring_t args[MAX_OPT_ARGS]; 13862306a36Sopenharmony_ci int option; 13962306a36Sopenharmony_ci int pipefd = -1; 14062306a36Sopenharmony_ci kuid_t uid; 14162306a36Sopenharmony_ci kgid_t gid; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci root->i_uid = current_uid(); 14462306a36Sopenharmony_ci root->i_gid = current_gid(); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci sbi->min_proto = AUTOFS_MIN_PROTO_VERSION; 14762306a36Sopenharmony_ci sbi->max_proto = AUTOFS_MAX_PROTO_VERSION; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci sbi->pipefd = -1; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (!options) 15262306a36Sopenharmony_ci return 1; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci while ((p = strsep(&options, ",")) != NULL) { 15562306a36Sopenharmony_ci int token; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (!*p) 15862306a36Sopenharmony_ci continue; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci token = match_token(p, tokens, args); 16162306a36Sopenharmony_ci switch (token) { 16262306a36Sopenharmony_ci case Opt_fd: 16362306a36Sopenharmony_ci if (match_int(args, &pipefd)) 16462306a36Sopenharmony_ci return 1; 16562306a36Sopenharmony_ci sbi->pipefd = pipefd; 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci case Opt_uid: 16862306a36Sopenharmony_ci if (match_int(args, &option)) 16962306a36Sopenharmony_ci return 1; 17062306a36Sopenharmony_ci uid = make_kuid(current_user_ns(), option); 17162306a36Sopenharmony_ci if (!uid_valid(uid)) 17262306a36Sopenharmony_ci return 1; 17362306a36Sopenharmony_ci root->i_uid = uid; 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci case Opt_gid: 17662306a36Sopenharmony_ci if (match_int(args, &option)) 17762306a36Sopenharmony_ci return 1; 17862306a36Sopenharmony_ci gid = make_kgid(current_user_ns(), option); 17962306a36Sopenharmony_ci if (!gid_valid(gid)) 18062306a36Sopenharmony_ci return 1; 18162306a36Sopenharmony_ci root->i_gid = gid; 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci case Opt_pgrp: 18462306a36Sopenharmony_ci if (match_int(args, &option)) 18562306a36Sopenharmony_ci return 1; 18662306a36Sopenharmony_ci *pgrp = option; 18762306a36Sopenharmony_ci *pgrp_set = true; 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci case Opt_minproto: 19062306a36Sopenharmony_ci if (match_int(args, &option)) 19162306a36Sopenharmony_ci return 1; 19262306a36Sopenharmony_ci sbi->min_proto = option; 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci case Opt_maxproto: 19562306a36Sopenharmony_ci if (match_int(args, &option)) 19662306a36Sopenharmony_ci return 1; 19762306a36Sopenharmony_ci sbi->max_proto = option; 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci case Opt_indirect: 20062306a36Sopenharmony_ci set_autofs_type_indirect(&sbi->type); 20162306a36Sopenharmony_ci break; 20262306a36Sopenharmony_ci case Opt_direct: 20362306a36Sopenharmony_ci set_autofs_type_direct(&sbi->type); 20462306a36Sopenharmony_ci break; 20562306a36Sopenharmony_ci case Opt_offset: 20662306a36Sopenharmony_ci set_autofs_type_offset(&sbi->type); 20762306a36Sopenharmony_ci break; 20862306a36Sopenharmony_ci case Opt_strictexpire: 20962306a36Sopenharmony_ci sbi->flags |= AUTOFS_SBI_STRICTEXPIRE; 21062306a36Sopenharmony_ci break; 21162306a36Sopenharmony_ci case Opt_ignore: 21262306a36Sopenharmony_ci sbi->flags |= AUTOFS_SBI_IGNORE; 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci default: 21562306a36Sopenharmony_ci return 1; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci return (sbi->pipefd < 0); 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciint autofs_fill_super(struct super_block *s, void *data, int silent) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct inode *root_inode; 22462306a36Sopenharmony_ci struct dentry *root; 22562306a36Sopenharmony_ci struct file *pipe; 22662306a36Sopenharmony_ci struct autofs_sb_info *sbi; 22762306a36Sopenharmony_ci struct autofs_info *ino; 22862306a36Sopenharmony_ci int pgrp = 0; 22962306a36Sopenharmony_ci bool pgrp_set = false; 23062306a36Sopenharmony_ci int ret = -EINVAL; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 23362306a36Sopenharmony_ci if (!sbi) 23462306a36Sopenharmony_ci return -ENOMEM; 23562306a36Sopenharmony_ci pr_debug("starting up, sbi = %p\n", sbi); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci s->s_fs_info = sbi; 23862306a36Sopenharmony_ci sbi->magic = AUTOFS_SBI_MAGIC; 23962306a36Sopenharmony_ci sbi->pipefd = -1; 24062306a36Sopenharmony_ci sbi->pipe = NULL; 24162306a36Sopenharmony_ci sbi->exp_timeout = 0; 24262306a36Sopenharmony_ci sbi->oz_pgrp = NULL; 24362306a36Sopenharmony_ci sbi->sb = s; 24462306a36Sopenharmony_ci sbi->version = 0; 24562306a36Sopenharmony_ci sbi->sub_version = 0; 24662306a36Sopenharmony_ci sbi->flags = AUTOFS_SBI_CATATONIC; 24762306a36Sopenharmony_ci set_autofs_type_indirect(&sbi->type); 24862306a36Sopenharmony_ci sbi->min_proto = 0; 24962306a36Sopenharmony_ci sbi->max_proto = 0; 25062306a36Sopenharmony_ci mutex_init(&sbi->wq_mutex); 25162306a36Sopenharmony_ci mutex_init(&sbi->pipe_mutex); 25262306a36Sopenharmony_ci spin_lock_init(&sbi->fs_lock); 25362306a36Sopenharmony_ci sbi->queues = NULL; 25462306a36Sopenharmony_ci spin_lock_init(&sbi->lookup_lock); 25562306a36Sopenharmony_ci INIT_LIST_HEAD(&sbi->active_list); 25662306a36Sopenharmony_ci INIT_LIST_HEAD(&sbi->expiring_list); 25762306a36Sopenharmony_ci s->s_blocksize = 1024; 25862306a36Sopenharmony_ci s->s_blocksize_bits = 10; 25962306a36Sopenharmony_ci s->s_magic = AUTOFS_SUPER_MAGIC; 26062306a36Sopenharmony_ci s->s_op = &autofs_sops; 26162306a36Sopenharmony_ci s->s_d_op = &autofs_dentry_operations; 26262306a36Sopenharmony_ci s->s_time_gran = 1; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci /* 26562306a36Sopenharmony_ci * Get the root inode and dentry, but defer checking for errors. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ci ino = autofs_new_ino(sbi); 26862306a36Sopenharmony_ci if (!ino) { 26962306a36Sopenharmony_ci ret = -ENOMEM; 27062306a36Sopenharmony_ci goto fail_free; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci root_inode = autofs_get_inode(s, S_IFDIR | 0755); 27362306a36Sopenharmony_ci root = d_make_root(root_inode); 27462306a36Sopenharmony_ci if (!root) { 27562306a36Sopenharmony_ci ret = -ENOMEM; 27662306a36Sopenharmony_ci goto fail_ino; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci pipe = NULL; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci root->d_fsdata = ino; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* Can this call block? */ 28362306a36Sopenharmony_ci if (parse_options(data, root_inode, &pgrp, &pgrp_set, sbi)) { 28462306a36Sopenharmony_ci pr_err("called with bogus options\n"); 28562306a36Sopenharmony_ci goto fail_dput; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* Test versions first */ 28962306a36Sopenharmony_ci if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION || 29062306a36Sopenharmony_ci sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) { 29162306a36Sopenharmony_ci pr_err("kernel does not match daemon version " 29262306a36Sopenharmony_ci "daemon (%d, %d) kernel (%d, %d)\n", 29362306a36Sopenharmony_ci sbi->min_proto, sbi->max_proto, 29462306a36Sopenharmony_ci AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION); 29562306a36Sopenharmony_ci goto fail_dput; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* Establish highest kernel protocol version */ 29962306a36Sopenharmony_ci if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION) 30062306a36Sopenharmony_ci sbi->version = AUTOFS_MAX_PROTO_VERSION; 30162306a36Sopenharmony_ci else 30262306a36Sopenharmony_ci sbi->version = sbi->max_proto; 30362306a36Sopenharmony_ci sbi->sub_version = AUTOFS_PROTO_SUBVERSION; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (pgrp_set) { 30662306a36Sopenharmony_ci sbi->oz_pgrp = find_get_pid(pgrp); 30762306a36Sopenharmony_ci if (!sbi->oz_pgrp) { 30862306a36Sopenharmony_ci pr_err("could not find process group %d\n", 30962306a36Sopenharmony_ci pgrp); 31062306a36Sopenharmony_ci goto fail_dput; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci } else { 31362306a36Sopenharmony_ci sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID); 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (autofs_type_trigger(sbi->type)) 31762306a36Sopenharmony_ci __managed_dentry_set_managed(root); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci root_inode->i_fop = &autofs_root_operations; 32062306a36Sopenharmony_ci root_inode->i_op = &autofs_dir_inode_operations; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci pr_debug("pipe fd = %d, pgrp = %u\n", 32362306a36Sopenharmony_ci sbi->pipefd, pid_nr(sbi->oz_pgrp)); 32462306a36Sopenharmony_ci pipe = fget(sbi->pipefd); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (!pipe) { 32762306a36Sopenharmony_ci pr_err("could not open pipe file descriptor\n"); 32862306a36Sopenharmony_ci goto fail_put_pid; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci ret = autofs_prepare_pipe(pipe); 33162306a36Sopenharmony_ci if (ret < 0) 33262306a36Sopenharmony_ci goto fail_fput; 33362306a36Sopenharmony_ci sbi->pipe = pipe; 33462306a36Sopenharmony_ci sbi->flags &= ~AUTOFS_SBI_CATATONIC; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* 33762306a36Sopenharmony_ci * Success! Install the root dentry now to indicate completion. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci s->s_root = root; 34062306a36Sopenharmony_ci return 0; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* 34362306a36Sopenharmony_ci * Failure ... clean up. 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_cifail_fput: 34662306a36Sopenharmony_ci pr_err("pipe file descriptor does not contain proper ops\n"); 34762306a36Sopenharmony_ci fput(pipe); 34862306a36Sopenharmony_cifail_put_pid: 34962306a36Sopenharmony_ci put_pid(sbi->oz_pgrp); 35062306a36Sopenharmony_cifail_dput: 35162306a36Sopenharmony_ci dput(root); 35262306a36Sopenharmony_ci goto fail_free; 35362306a36Sopenharmony_cifail_ino: 35462306a36Sopenharmony_ci autofs_free_ino(ino); 35562306a36Sopenharmony_cifail_free: 35662306a36Sopenharmony_ci kfree(sbi); 35762306a36Sopenharmony_ci s->s_fs_info = NULL; 35862306a36Sopenharmony_ci return ret; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistruct inode *autofs_get_inode(struct super_block *sb, umode_t mode) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci struct inode *inode = new_inode(sb); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (inode == NULL) 36662306a36Sopenharmony_ci return NULL; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci inode->i_mode = mode; 36962306a36Sopenharmony_ci if (sb->s_root) { 37062306a36Sopenharmony_ci inode->i_uid = d_inode(sb->s_root)->i_uid; 37162306a36Sopenharmony_ci inode->i_gid = d_inode(sb->s_root)->i_gid; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); 37462306a36Sopenharmony_ci inode->i_ino = get_next_ino(); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (S_ISDIR(mode)) { 37762306a36Sopenharmony_ci set_nlink(inode, 2); 37862306a36Sopenharmony_ci inode->i_op = &autofs_dir_inode_operations; 37962306a36Sopenharmony_ci inode->i_fop = &autofs_dir_operations; 38062306a36Sopenharmony_ci } else if (S_ISLNK(mode)) { 38162306a36Sopenharmony_ci inode->i_op = &autofs_symlink_inode_operations; 38262306a36Sopenharmony_ci } else 38362306a36Sopenharmony_ci WARN_ON(1); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci return inode; 38662306a36Sopenharmony_ci} 387